Emacs Configuration

Table of Contents

Prologue

A Straightforward Emacs Configuration Bundle.

This is my Emacs configuration in literate form, and it is towards macOS. I am not sure if it would work well well on Linux or Windows.

My Blog
https://nasy.moe/
Complete Literate Configuration
https://emacs.nasy.moe/

NOTICE

  • Use straight.el to manage packages.
  • For macOS GUI.
  • Now only tested with GNU Emacs 26.2/27.0.50 of macOS 10.14.

Screenshots

screenshot1.png

screenshot2.png

screenshot3.png

Dependencies

  • Emacs
  • git
  • make

Installation

To install, clone this repo to ~/.emacs.d :

git clone https://github.com/nasyxx/emacs.d.git ~/.emacs.d
make generate

Upon the first time staring up emacs, other third-party packages will be automatically clone to the straight: folder and installed. If you encounter any errors at that stage, try restarting Emacs, and maybe running make clean-build before doing so.

You can regenerate init.el by make generate.

Updates

Update this config with running make update or git pull after a make clean-build and restart Emacs.

And I guess you'll need to update third-party packages regularly too if you have not modificated the straight-check-for-modifications in config/nasy-config.el:

  • M-x straight-pull-all RET
  • M-x straight-rebuild-all RET

If you encounter any errors while updating, you may need to kill Emacs and run make clean. If you still meet errors after doing that, you probably need to run make clean-all and restart Emacs.

Custom Configuration

Example Custom Configuration

To add your own customization, use M-x customize etc. and/or create a file custom/user-config.el which looks like this (when you make or make generate, below will generate to custom/user-config-example.el ):

(setq-default
 ;; calendar-latitude     24.8801
 ;; calendar-longitude    102.8329
 ;; user-mail-address     "[email protected]"
 ;; initial-buffer-choice #'(lambda () (get-buffer "*dashboard*"))
 cnfonts-profiles      '("nasy-profile" "profile1" "profile2" "profile3")
 *theme*               'doom-vibrant
 *debug*               t
 *struct-hs*           nil
 ;; *vterm*               "/Users/Nasy/src/emacs-libvterm"
 *risky-var*           nil
 *dvorak*              nil
 *font-cjk*            "Kaiti SC"
 *font-weight-cjk*     'normal)
(provide 'user-config-example)

dashboard

If you want to start with dashboard, you need to set

(setq initial-buffer-choice #'(lambda () (get-buffer "*dashboard*"))

in your custom/user-config.el.

Launching emacs from command line with a file name causes errors. Please refer to the issue here. Hope someone could fix it.

NOTICE:

  • Functions added to nasy/config-before-hook will be run before loading custom.el.
  • Functions added to nasy/config-after-hook will be run after init.

Features

Summary

Package Manager
straight.el with –depth=1
Font
Languages
  • lsp-mode/lsp-dap
  • Haskell
  • Python
  • Lisp
  • HTML/CSS/JavaScript/TypeScript
  • Rust
Themes
  • Doom Themes
  • Darktooth
  • Soothe

The Configuration

See the complete literate config here:

Html

Source

One thing to note is that this file generates a file named init.el. You should not edit that file directly and make any changes here and regenerate it from Emacs org-mode using C-c C-v t .

Bootstrap

File Header

This includes some necessary headers.

;;; init.el --- Nasy's emacs.d init file.            -*- lexical-binding: t; -*-
;; Copyright (C) 2018  Nasy

;; Author: Nasy <[email protected]>

;;; Commentary:

;; Nasy's emacs.d init file.  For macOS and Emacs 26, Emacs 27.

Lexical Binding

This makes it so that the file that is produced from tangling this file uses lexical scoping.

(setq-default lexical-binding t)

Some Default Settings

Some default settings are here, including debug-on-error, message-log-max, load-prefer-newer and ad-redefinition-action.

(setq-default debug-on-error         t
              message-log-max        t
              load-prefer-newer      t
              ad-redefinition-action 'accept)

Macros & Alias

Useful Macros and Alias.

(defmacro λ! (&rest body)
  "A shortcut for inline interactive lambdas."
  (declare (doc-string 1))
  `(lambda () (interactive) ,@body))

(defalias 'lambda! 'λ!)

Is A Mac?

If this os is macOS?

(defconst *is-a-mac* (eq system-type 'darwin))

Packages Manager

I use straight.el as my packages manager.

https://github.com/raxod502/straight.el

(setq straight-recipes-gnu-elpa-use-mirror    t
      straight-repository-branch              "develop"
      straight-vc-git-default-clone-depth     1
      straight-enable-use-package-integration nil
      straight-check-for-modifications        '(find-when-checking))

(defvar bootstrap-version)

(let ((bootstrap-file
       (expand-file-name "straight/repos/straight.el/bootstrap.el" user-emacs-directory))
      (bootstrap-version 5))
  (unless (file-exists-p bootstrap-file)
    (with-current-buffer
        (url-retrieve-synchronously
         "https://raw.githubusercontent.com/raxod502/straight.el/develop/install.el"
         'silent 'inhibit-cookies)
      (goto-char (point-max))
      (eval-print-last-sexp)))
  (load bootstrap-file nil 'nomessage))

At the same time, I use use-package to manage packages' loading.

(straight-use-package 'use-package)

Garbage Collection

Use GCMH – the Garbage Collector Magic Hack – to adjust garbage collection.

https://gitlab.com/koral/gcmh

(straight-use-package 'gcmh)
(use-package gcmh
  :demand t
  :init
  (setq gcmh-verbose             t
        gcmh-lows-cons-threshold #x800000
        gcmh-high-cons-threshold #x800000
        gcmh-idle-delay          300)
  :config
  (gcmh-mode))

Benchmark

(straight-use-package 'benchmark-init)
(use-package benchmark-init
  :demand t
  :hook ((after-init . benchmark-init/deactivate)))

No Littering

https://github.com/emacscollective/no-littering

(straight-use-package 'no-littering)
(require 'no-littering)

Define Nasy Custom

Here includes all of the customizable variables of my configuration.

You can custom it in custom/user-config.el

Custom Config Hooks
(defvar nasy/config-before-hook nil
  "Hooks to run config functions before load custom.el.")

(defvar nasy/config-after-hook nil
  "Hooks to run config functions after.")

(add-hook 'nasy/config-after-hook
          #'(lambda () (message "Hi~ Hope you have fun with this config.")))

(add-hook 'after-init-hook
          #'(lambda () (run-hooks 'nasy/config-after-hook)))
Custom
(defgroup nasy nil
  "Nasy Emacs Custom Configurations."
  :group 'emacs)

(defcustom lisp-modes-hooks '(cider-repl-mode-hook
                              clojure-mode-hook
                              clojurec-mode-hook
                              clojurescript-mode-hook
                              clojurex-mode-hook
                              common-lisp-mode-hook
                              emacs-lisp-mode-hook
                              eshell-mode-hook
                              geiser-repl-mode-hook
                              gerbil-mode-hook
                              inf-clojure-mode-hook
                              inferior-emacs-lisp-mode-hook
                              inferior-lisp-mode-hook
                              inferior-scheme-mode-hook
                              lisp-interaction-mode-hook
                              lisp-mode-hook
                              monroe-mode-hook
                              racket-mode-hook
                              racket-repl-mode-hook
                              scheme-interaction-mode-hook
                              scheme-mode-hook
                              slime-repl-mode-hook
                              stumpwm-mode-hook)
  "List of lisp-related modes hooks."
  :type '(repeat symbol)
  :group 'nasy)

(defcustom *clangd* (executable-find "clangd")
  "Clangd path.  If nil, will not use clangd."
  :group 'nasy
  :type 'string)

(defcustom *ccls* (executable-find "ccls")  ;; macOS
  "Ccls path.  If nil, will not use ccls."
  :group 'nasy
  :type 'string)

(defcustom *eldoc-box* nil
  "Whether to use eloc-box or not."
  :group 'nasy
  :type 'boolean)

(defcustom *nix* nil
  "Nix path.  If nil, will not use nix."
  :group 'nasy
  :type 'string)

(defcustom *rust* (or (executable-find "rustc")
                      (executable-find "cargo")
                      (executable-find "rustup"))
  "The Rust path.  If nil, will not use Rust."
  :group 'nasy
  :type 'string)

(defcustom *rls* (executable-find "rls")
  "The rls path.  If nil, will not use rls."
  :group 'nasy
  :type 'string)

(defcustom *debug* t
  "Whether to use debug or not."
  :group 'nasy
  :type 'boolean)

(defcustom *server* t
  "Whether to use server or not."
  :group 'nasy
  :type 'boolean)

(defcustom *intero* t
  "Whether to use intero or not."
  :group 'nasy
  :type 'boolean)

(defcustom *struct-hs* (executable-find "structured-haskell-mode")
  "The structured-haskell-mode path.  If nil, will not use structured-haskell-mode."
  :group 'nasy
  :type 'string)

(defcustom *blacken* nil
  "Whether to use blacken or not."
  :group 'nasy
  :type 'boolean)

(defcustom *c-box* t
  "Whether to use company box or not."
  :group 'nasy
  :type 'boolean)

(defcustom *ivy-posframe* nil
  "Whether to use ivy-posframe or not."
  :group 'nasy
  :type 'boolean)

(defcustom *vterm* nil
  "Whether to use vterm or not."
  :group 'nasy
  :type 'boolean)

(defcustom *org-headline-rescale* t
  "Whether to rescale org-headline or not."
  :group 'nasy
  :type 'boolean)

(defcustom *ispell* (executable-find "aspell")
  "The Ispell.  If nil, will not use Ispell."
  :group 'nasy
  :type 'string)

(defcustom *theme* 'doom-dracula
  "The Theme."
  :group 'nasy
  :type 'symbol)

(defcustom *dvorak* nil
  "Whether to use dvorak or not."
  :group 'nasy
  :type 'boolean)

(defcustom *mouse-color* "black"
  "Mouse color."
  :group 'nasy
  :type 'string)

(defcustom *font* "OperatorMonoSSmLig Nerd Font"
 "The main font.  After change it, run `M-x nasy/set-font' to see the effect."
 :group 'nasy
 :type 'string)

(defcustom *font-size* 12.0
 "The main font.  After change it, run `M-x nasy/set-font' to see the effect."
 :group 'nasy
 :type 'float)

(defcustom *font-weight* 'normal
 "The main font.  After change it, run `M-x nasy/set-font' to see the effect."
 :group 'nasy
 :type 'symbol)

(defcustom *font-cjk* "Xingkai SC"
 "The cjk font.  After change it, run `M-x nasy/set-font' to see the effect."
 :group 'nasy
 :type 'string)

(defcustom *font-size-cjk* 16.0
 "The cjk font.  After change it, run `M-x nasy/set-font' to see the effect."
 :group 'nasy
 :type 'float)

(defcustom *font-weight-cjk* 'light
 "The cjk font.  After change it, run `M-x nasy/set-font' to see the effect."
 :group 'nasy
 :type 'symbol)
Default Settings
Company
(setq-default
 company-idle-delay .5)
Cursor
(setq-default
  blink-cursor-interval .6
  blink-matching-paren  t
  cursor-in-non-selected-windows t)

(blink-cursor-mode t)

(add-hook 'nasy/config-after-hook
          #'(lambda ()
              (when (fboundp 'set-mouse-color)
                (set-mouse-color *mouse-color*))))
Languages
(setq-default
 haskell-stylish-on-save nil
 blacken-line-length     80
 lsp-rust-rls-command    '("rls"))
Pandoc
(setq-default
 org-pandoc-options-for-context     '((template . "~/.emacs.d/nasy-context.tex"))  ;; I have no idea why I cannot set it as a variable.
 org-pandoc-options-for-context-pdf '((template . "~/.emacs.d/nasy-context.tex")))
Parens
(setq-default
 show-paren-style                                'parenthesis
 sp-autoinsert-quote-if-followed-by-closing-pair t
 sp-base-key-bindings                            'paredit
 sp-show-pair-from-inside                        t)
Scrolling
(setq hscroll-margin                  7
      scroll-margin                   7
      hscroll-step                    7
      scroll-step                     7
      scroll-conservatively           100000
      scroll-preserve-screen-position 'always
      mac-mouse-wheel-smooth-scroll    nil)
Shell
(setq-default
 shell-file-name "/bin/zsh")
Start
(setq-default
 initial-scratch-message     (concat ";; Happy hacking, " user-login-name " - Emacs ♥ you!\n\n")
 dashboard-banner-logo-title (concat ";; Happy hacking, " user-login-name " - Emacs ♥ you!\n\n")
 ;; initial-buffer-choice       #'(lambda () (get-buffer "*dashboard*"))  ;; It will cause error if you start emacs from Command line with file name
                                                                          ;; https://github.com/rakanalh/emacs-dashboard/issues/69
)
Visual
(setq-default
 fill-column                    80
 visual-fill-column-width       100
 word-wrap                      t
 highlight-indent-guides-method 'column
 tab-width                      8
 tooltip-delay                  1.5)
Whitespace
(setq-default
 whitespace-line-column 80
 whitespace-style       '(face spaces tabs newline
                          space-mark tab-mark newline-mark
                          lines-tail empty))
Mess
(setq-default
   bookmark-default-file (no-littering-expand-var-file-name ".bookmarks.el")
   buffers-menu-max-size 30
   case-fold-search      t
   column-number-mode    t
   dired-dwim-target     t
   ediff-split-window-function 'split-window-horizontally
   ediff-window-setup-function 'ediff-setup-windows-plain
   indent-tabs-mode      nil
   line-move-visual      t
   make-backup-files     nil
   mouse-yank-at-point   t
   require-final-newline t
   save-interprogram-paste-before-kill t
   set-mark-command-repeat-pop    t
   tab-always-indent              'complete
   truncate-lines                 nil
   truncate-partial-width-windows nil)

(when *is-a-mac*
  (setq line-move-visual nil))

(fset 'yes-or-no-p 'y-or-n-p)

(global-auto-revert-mode t)

(delete-selection-mode t)
Config After initialization
(defun nasy/config-after ()
  "Set configuration need to be set after init."
  (setq-default
   ;; helm-allow-mouse                  t
   ;; helm-follow-mode-persistent       t
   ;; helm-move-to-line-cycle-in-source nil
   ;; helm-source-names-using-follow    '("Buffers" "kill-buffer" "Occur")
   debug-on-error *debug*))


(add-hook 'nasy/config-after-hook  #'nasy/config-after)
Custom Faces
(defun nasy/set-face ()
  "Set custom face."
  (with-eval-after-load 'org
    (set-face-attribute 'org-meta-line               nil                                             :slant   'italic)
    (set-face-attribute 'org-block-begin-line        nil                                             :slant   'italic)
    (set-face-attribute 'org-block-end-line          nil                                             :slant   'italic)
    (when *org-headline-rescale*
      (set-face-attribute 'org-level-1 nil :height 1.6 :inherit 'outline-1)
      (set-face-attribute 'org-level-2 nil :height 1.4 :inherit 'outline-2)
      (set-face-attribute 'org-level-3 nil :height 1.2 :inherit 'outline-3)
      (set-face-attribute 'org-level-4 nil :height 1.1 :inherit 'outline-4)))
  (set-face-attribute 'font-lock-comment-face      nil                                             :slant   'italic)
  (set-face-attribute 'font-lock-keyword-face      nil                                             :slant   'italic)
  (set-face-attribute 'show-paren-match            nil :background "#a1de93" :foreground "#705772" :weight  'ultra-bold)
  (set-face-attribute 'sp-show-pair-match-face     nil :background "#a1de93" :foreground "#705772" :weight  'ultra-bold))
(add-hook 'nasy/config-after-hook #'nasy/set-face)

Expand load-path and load user custom

(add-to-list 'load-path (expand-file-name "custom" user-emacs-directory))
(require 'user-config-example)
(require 'user-config nil t)

Key Definition

General

https://github.com/noctuid/general.el

(straight-use-package 'general)
(use-package general
  :init
  (defalias 'gsetq #'general-setq)
  (defalias 'gsetq-local #'general-setq-local)
  (defalias 'gsetq-default #'general-setq-default))
macOS Key Bindings
(when *is-a-mac*
  (gsetq mac-option-modifier  'meta
         mac-command-modifier 'hyper
         mac-right-command-modifier 'control)

  (general-define-key
   "C-z" 'stop-minimizing-window

   ;; cursor Movement
   "H-<up>"   'beginning-of-buffer
   "H-<down>" 'end-of-buffer
   "H-l"      'goto-line

   ;; text Operations
   "H-a" 'mark-whole-buffer
   "H-v" 'yank
   "H-c" 'kill-ring-save
   "H-s" 'save-buffer
   "H-z" 'undo
   "H-w" (lambda! (delete-window))
   "M-¥" (lambda! (insert "\\"))
   "H-<backspace>" (lambda! (kill-line 0)))

  ;; unset
  (global-unset-key (kbd "<magnify-down>"))
  (global-unset-key (kbd "<magnify-up>")))
Dvorak Key Bindings
(add-hook #'nasy/config-after-hook
          #'(lambda ()
              (when *dvorak*
                (general-define-key
                 :keymaps 'key-translation-map
                 "C-," "C-x"
                 "C-x" "C-,"
                 "M-," "M-x"
                 "M-x" "M-,"
                 "C-c" "C-."
                 "C-." "C-c"
                 "M-c" "M-."
                 "M-." "M-c"))))
Toogle Dvorak Key Bindings
(defun nasy/toogle-dvorak ()
  "Toogle dvorak key bindings."
  (interactive)
  (if (not *dvorak*)
      (progn
        (general-define-key
         :keymaps 'key-translation-map
         "C-," "C-x"
         "C-x" "C-,"
         "M-," "M-x"
         "M-x" "M-,"
         "C-c" "C-."
         "C-." "C-c"
         "M-c" "M-."
         "M-." "M-c")
        (gsetq *dvorak* t)
        (message "Use Dvorak key bindings."))
    (progn
      (general-define-key
         :keymaps 'key-translation-map
         "C-," nil
         "C-x" nil
         "M-," nil
         "M-x" nil
         "C-c" nil
         "C-." nil
         "M-c" nil
         "M-." nil)
      (gsetq *dvorak* nil)
      (message "Use normal key bindings."))))
Mouse Key Bindings
(general-define-key
 "<mouse-4>" (lambda! (scroll-down 1))
 "<mouse-5>" (lambda! (scroll-up 1)))

Load Org

When using straight.el, the org version is needed to custom set.

(straight-use-package 'org-plus-contrib)

Core

macOS Frame
(when *is-a-mac*
  (add-to-list 'default-frame-alist
               '(ns-transparent-titlebar . t))

  (add-to-list 'default-frame-alist
               '(ns-appearance . dark))

  (add-to-list 'default-frame-alist
               '(alpha . (80 . 75)))

  (defun stop-minimizing-window ()
    "Stop minimizing window under macOS."
    (interactive)
    (unless (and *is-a-mac*
                 window-system)
      (suspend-frame))))
Disable Some Features
(setq use-file-dialog        nil
      use-dialog-box         nil
      inhibit-startup-screen t)

(when (fboundp 'tool-bar-mode)
  (tool-bar-mode -1))

(when (fboundp 'set-scroll-bar-mode)
  (set-scroll-bar-mode nil))
Compile
;; https://github.com/jwiegley/emacs-async
(straight-use-package 'async)
(use-package dired-async
  :commands dired-async-mode)
(use-package async-bytecomp
  :config
  (gsetq async-bytecomp-allowed-packages '(all))
  (async-bytecomp-package-mode))

;; (straight-use-package 'auto-compile)
;; (require 'auto-compile)
;; (auto-compile-on-load-mode)
;; (auto-compile-on-save-mode)

(setq-default compilation-scroll-output t)

;; https://github.com/jwiegley/alert
(straight-use-package 'alert)
(use-package alert
  :defer    t
  :preface
  (defun alert-after-compilation-finish (buf result)
    "Use `alert' to report compilation RESULT if BUF is hidden."
    (when (buffer-live-p buf)
      (unless (catch 'is-visible
                (walk-windows (lambda (w)
                                (when (eq (window-buffer w) buf)
                                  (throw 'is-visible t))))
                nil)
        (alert (concat "Compilation " result)
               :buffer buf
               :category 'compilation)))))


(use-package compile
  :defer t
  :preface
  (defvar nasy/last-compilation-buffer nil
    "The last buffer in which compilation took place.")

  (defun nasy/save-compilation-buffer (&rest _)
    "Save the compilation buffer to find it later."
    (setq nasy/last-compilation-buffer next-error-last-buffer))
  (advice-add 'compilation-start :after 'nasy/save-compilation-buffer)

  (defun nasy/find-prev-compilation (orig &rest args)
    "Find the previous compilation buffer, if present, and recompile there."
    (if (and (null edit-command)
             (not (derived-mode-p 'compilation-mode))
             nasy:last-compilation-buffer
             (buffer-live-p (get-buffer nasy/last-compilation-buffer)))
        (with-current-buffer nasy/last-compilation-buffer
          (apply orig args))
      (apply orig args)))
  :bind (([f6] . recompile))
  :hook ((compilation-finish-functions . alert-after-compilation-finish)))

(use-package ansi-color
  :defer    t
  :preface
  (defun colourise-compilation-buffer ()
    (when (eq major-mode 'compilation-mode)
      (ansi-cOLOR-APPLY-on-region compilation-filter-start (point-max))))
  :hook ((compilation-filter . colourise-compilation-buffer)))
Auto Compression
(require 'jka-compr)
(auto-compression-mode)
History, Saving and Session
(gsetq desktop-path              (list user-emacs-directory no-littering-var-directory)
       desktop-dirname           (list user-emacs-directory no-littering-var-directory)
       desktop-auto-save-timeout 600)
(desktop-save-mode t)
(gsetq desktop-save 'if-exists)


(defun nasy/desktop-time-restore (orig &rest args)
  (let ((start-time (current-time)))
    (prog1
        (apply orig args)
      (message "Desktop restored in %.2fms"
               (benchmark-init/time-subtract-millis (current-time)
                                               start-time)))))
(advice-add 'desktop-read :around 'nasy/desktop-time-restore)

(defun nasy/desktop-time-buffer-create (orig ver filename &rest args)
  (let ((start-time (current-time)))
    (prog1
        (apply orig ver filename args)
      (message "Desktop: %.2fms to restore %s"
               (benchmark-init/time-subtract-millis (current-time)
                                               start-time)
               (when filename
                 (abbreviate-file-name filename))))))
(advice-add 'desktop-create-buffer :around 'nasy/desktop-time-buffer-create)

(gsetq kill-ring-max 300)

(gsetq history-length 3000
       history-delete-duplicates t
       savehist-additional-variables
       '(mark-ring
         global-mark-ring
         search-ring
         regexp-search-ring
         extended-command-history)
       savehist-autosave-interval 60)

(add-hook #'after-init-hook #'savehist-mode)

(straight-use-package 'session)
(use-package session
  :defer    t
  :hook ((after-init . session-initialize))
  :init
  (gsetq session-save-file (no-littering-expand-var-file-name ".session")
         session-name-disable-regexp "\\(?:\\`'/tmp\\|\\.git/[A-Z_]+\\'\\)"
         session-save-file-coding-system 'utf-8
         desktop-globals-to-save
         (append '((comint-input-ring        . 50)
                   (compile-history          . 30)
                   desktop-missing-file-warning
                   (dired-regexp-history     . 20)
                   (extended-command-history . 30)
                   (face-name-history        . 20)
                   (file-name-history        . 100)
                   (grep-find-history        . 30)
                   (grep-history             . 30)
                   (ivy-history              . 100)
                   (magit-revision-history   . 50)
                   (minibuffer-history       . 50)
                   (org-clock-history        . 50)
                   (org-refile-history       . 50)
                   (org-tags-history         . 50)
                   (query-replace-history    . 60)
                   (read-expression-history  . 60)
                   (regexp-history           . 60)
                   (regexp-search-ring       . 20)
                   register-alist
                   (search-ring              . 20)
                   (shell-command-history    . 50)
                   tags-file-name
                   tags-table-list
                   kill-ring))))
Auto Save (Super Save)

I use super save to auto save files.

(straight-use-package 'super-save)
(use-package super-save
  :ghook 'after-init-hook
  :gfhook '(lambda () (remove-hook #'mouse-leave-buffer-hook #'super-save-command))
  :init (gsetq super-save-auto-save-when-idle nil
               super-save-remote-files        nil
               super-save-hook-triggers       nil
               super-save-triggers
               '(ibuffer other-window windmove-up windmove-down windmove-left windmove-right next-buffer previous-buffer)))
Text Scale
(straight-use-package 'default-text-scale)
(use-package default-text-scale
  :commands default-text-scale-mode
  :ghook 'after-init-hook)

Custom Functions

Reload the init-file
(defun radian-reload-init ()
  "Reload init.el."
  (interactive)
  (straight-transaction
    (straight-mark-transaction-as-init)
    (message "Reloading init.el...")
    (load user-init-file nil 'nomessage)
    (message "Reloading init.el... done.")))

(defun radian-eval-buffer ()
  "Evaluate the current buffer as Elisp code."
  (interactive)
  (message "Evaluating %s..." (buffer-name))
  (straight-transaction
    (if (null buffer-file-name)
        (eval-buffer)
      (when (string= buffer-file-name user-init-file)
        (straight-mark-transaction-as-init))
      (load-file buffer-file-name)))
  (message "Evaluating %s... done." (buffer-name)))
Insert Date
(defun nasy:insert-current-date ()
  "Insert current date."
  (interactive)
  (insert (shell-command-to-string "echo -n $(date +'%b %d, %Y')")))

(defun nasy:insert-current-filename ()
  "Insert current buffer filename."
  (interactive)
  (insert (file-relative-name buffer-file-name)))
Posframe Helper
(defun posframe-poshandler-frame-top-center (info)
  (cons (/ (- (plist-get info :parent-frame-width)
              (plist-get info :posframe-width))
           2)
        (round (* 0.02 (x-display-pixel-height)))))

Window

Ace Window
(straight-use-package 'ace-window)
(use-package ace-window
  :bind (("M-o" . ace-window))
  :config
  (set-face-attribute
   'aw-leading-char-face nil
   :foreground "deep sky blue"
   :weight 'bold
   :height 3.0)
  (set-face-attribute
   'aw-mode-line-face nil
   :inherit 'mode-line-buffer-id
   :foreground "lawn green")
  (gsetq-default cursor-in-non-selected-windows 'hollow)
  (gsetq aw-reverse-frame-list t
         aw-keys '(?a ?s ?d ?f ?j ?k ?l)
         aw-dispatch-always t
         aw-dispatch-alist
         '((?w hydra-window-size/body)
           (?o hydra-window-scroll/body)
           (?\; hydra-frame-window/body)
           (?0 delete-frame)
           (?1 delete-other-frames)
           (?2 make-frame)
           (?x aw-delete-window "Ace - Delete Window")
           (?c aw-swap-window "Ace - Swap Window")
           (?n aw-flip-window)
           (?v aw-split-window-vert "Ace - Split Vert Window")
           (?h aw-split-window-horz "Ace - Split Horz Window")
           (?\- aw-split-window-vert "Ace - Split Vert Window")
           (?\| aw-split-window-horz "Ace - Split Horz Window")
           (?m delete-other-windows "Ace - Maximize Window")
           (?g delete-other-windows)
           (?b balance-windows)
           (?u (lambda ()
                 (progn
                   (winner-undo)
                   (setq this-command 'winner-undo)))
               (?r winner-redo))))
  (with-eval-after-load 'hydra
    (defhydra hydra-window-size (:color violet)
      "Windows size"
      ("h" shrink-window-horizontally "shrink horizontal")
      ("j" shrink-window "shrink vertical")
      ("k" enlarge-window "enlarge vertical")
      ("l" enlarge-window-horizontally "enlarge horizontal"))
    (defhydra hydra-window-scroll (:color violet)
      "Scroll other window"
      ("n" joe-scroll-other-window "scroll")
      ("p" joe-scroll-other-window-down "scroll down"))
    (defhydra hydra-frame-window (:color violet :hint nil)
      "
^Delete^                       ^Frame resize^             ^Window^                Window Size^^^^^^   ^Text^                         (__)
_0_: delete-frame              _g_: resize-frame-right    _t_: toggle               ^ ^ _k_ ^ ^        _K_                           (oo)
_1_: delete-other-frames       _H_: resize-frame-left     _e_: ace-swap-win         _h_ ^+^ _l_        ^+^                     /------\\/
_2_: make-frame                _F_: fullscreen            ^ ^                       ^ ^ _j_ ^ ^        _J_                    / |    ||
_d_: kill-and-delete-frame     _n_: new-frame-right       _w_: ace-delete-window    _b_alance^^^^      ^ ^                   *  /\\---/\\  ~~  C-x f ;
"
      ("0" delete-frame :exit t)
      ("1" delete-other-frames :exit t)
      ("2" make-frame  :exit t)
      ("b" balance-windows)
      ("d" kill-and-delete-frame :exit t)
      ("e" ace-swap-window)
      ("F" toggle-frame-fullscreen)   ;; is <f11>
      ("g" resize-frame-right :exit t)
      ("H" resize-frame-left :exit t)  ;; aw-dispatch-alist uses h, I rebind here so hjkl can be used for size
      ("n" new-frame-right :exit t)
      ("r" reverse-windows)
      ("t" toggle-window-spilt)
      ("w" ace-delete-window :exit t)
      ("x" delete-frame :exit t)
      ("K" text-scale-decrease)
      ("J" text-scale-increase)
      ("h" shrink-window-horizontally)
      ("k" shrink-window)
      ("j" enlarge-window)
      ("l" enlarge-window-horizontally)))
  (ace-window-display-mode t))
Switch-Window
(straight-use-package 'switch-window)
(use-package switch-window
  :init (gsetq-default switch-window-shortcut-style 'alphabet
                       switch-window-timeout nil)
  :config
  ;; When splitting window, show (other-buffer) in the new window
  (defun split-window-func-with-other-buffer (split-function)
    "Split window with `SPLIT-FUNCTION'."
    (lambda (&optional arg)
      "Split this window and switch to the new window unless ARG is provided."
      (interactive "P")
      (funcall split-function)
      (let ((target-window (next-window)))
        (set-window-buffer target-window (other-buffer))
        (unless arg
          (select-window target-window)))))

  (defun toggle-delete-other-windows ()
    "Delete other windows in frame if any, or restore previous window config."
    (interactive)
    (if (and winner-mode
             (equal (selected-window) (next-window)))
        (winner-undo)
      (delete-other-windows)))

  (defun split-window-horizontally-instead ()
    "Kill any other windows and re-split such that the current window is on the top half of the frame."
    (interactive)
    (let ((other-buffer (and (next-window) (window-buffer (next-window)))))
      (delete-other-windows)
      (split-window-horizontally)
      (when other-buffer
        (set-window-buffer (next-window) other-buffer))))

  (defun split-window-vertically-instead ()
    "Kill any other windows and re-split such that the current window is on the left half of the frame."
    (interactive)
    (let ((other-buffer (and (next-window) (window-buffer (next-window)))))
      (delete-other-windows)
      (split-window-vertically)
      (when other-buffer
        (set-window-buffer (next-window) other-buffer))))

  ;; Borrowed from http://postmomentum.ch/blog/201304/blog-on-emacs
  (defun nasy/split-window()
    "Split the window to see the most recent buffer in the other window.
  Call a second time to restore the original window configuration."
    (interactive)
    (if (eq last-command 'nasy-split-window)
        (progn
          (jump-to-register :nasy-split-window)
          (setq this-command 'nasy-unsplit-window))
      (window-configuration-to-register :nasy/split-window)
      (switch-to-buffer-other-window nil)))

  (general-define-key
   :prefix "C-x"
   "1" 'toggle-delete-other-windows
   "2" (split-window-func-with-other-buffer 'split-window-vertically)
   "3" (split-window-func-with-other-buffer 'split-window-horizontally)
   "|" 'split-window-horizontally-instead
   "_" 'split-window-vertically-instead
   "x" 'nasy/split-window
   "o" 'switch-window))

Basic

Disable Mouse
(straight-use-package 'disable-mouse)
Minibuffer
(setq enable-recursive-minibuffers t)

(minibuffer-depth-indicate-mode)

;; https://www.reddit.com/r/emacs/comments/4d8gvt/how_do_i_automatically_close_the_minibuffer_after/
(defun helper/kill-minibuffer ()
  "Exit the minibuffer if it is active."
  (when (and (>= (recursion-depth) 1)
           (active-minibuffer-window))
    (abort-recursive-edit)))

(add-hook #'mouse-leave-buffer-hook #'helper/kill-minibuffer)
Scratch Message
(straight-use-package 'scratch)
Shell & Term
Shell
(require 'shell)

(straight-use-package 'cmd-to-echo)


(straight-use-package 'command-log-mode)


(defun nasy:shell-command-in-view-mode (start end command &optional output-buffer replace &rest other-args)
  "Put \"*Shell Command Output*\" buffers into view-mode."
  (unless (or output-buffer replace)
    (with-current-buffer "*Shell Command Output*"
      (view-mode 1))))
(advice-add 'shell-command-on-region :after 'nasy:shell-command-in-view-mode)


(straight-use-package 'exec-path-from-shell)
(use-package exec-path-from-shell
  :demand   *is-a-mac*
  :preface
  ;; Non-Forking Shell Command To String
  ;; https://github.com/bbatsov/projectile/issues/1044
  ;;--------------------------------------------------------------------------

  (defun call-process-to-string (program &rest args)
    (with-temp-buffer
      (apply 'call-process program nil (current-buffer) nil args)
      (buffer-string)))

  (defun get-call-process-args-from-shell-command (command)
    (cl-destructuring-bind
        (the-command . args) (split-string command " ")
      (let ((binary-path (executable-find the-command)))
        (when binary-path
          (cons binary-path args)))))

  (defun shell-command-to-string (command)
    (let ((call-process-args
           (get-call-process-args-from-shell-command command)))
      (if call-process-args
          (apply 'call-process-to-string call-process-args)
        (shell-command-to-string command))))

  (defun try-call-process (command)
    (let ((call-process-args
           (get-call-process-args-from-shell-command command)))
      (if call-process-args
          (apply 'call-process-to-string call-process-args))))

  (advice-add 'shell-command-to-string :before-until 'try-call-process)

  (straight-use-package 'noflet)

  (defun call-with-quick-shell-command (fn &rest args)
    (noflet ((shell-command-to-string
              (&rest args)
              (or (apply 'try-call-process args) (apply this-fn args))))
            (apply fn args)))

  (advice-add 'projectile-find-file :around 'call-with-quick-shell-command)
  :init (gsetq shell-command-switch "-ic")
  :config
  (when nil (message "PATH: %s, INFO: %s" (getenv "PATH")
                     (getenv "ENVIRONMENT_SETUP_DONE"))
        (setq exec-path-from-shell-debug t))
  (gsetq exec-path-from-shell-arguments (list "-l")
         exec-path-from-shell-check-startup-files nil)
  (add-to-list 'exec-path-from-shell-variables "SHELL")
  (add-to-list 'exec-path-from-shell-variables "GOPATH")
  (add-to-list 'exec-path-from-shell-variables "ENVIRONMENT_SETUP_DONE")
  (add-to-list 'exec-path-from-shell-variables "PYTHONPATH")
  (add-to-list 'exec-path-from-shell-variables "PKG_CONFIG_PATH")
  (exec-path-from-shell-initialize)
  (add-to-list 'exec-path "~/.pyenv/shims/"))
Term

Emacs libvterm intergration

https://github.com/akermu/emacs-libvterm

(when *vterm*
  (progn
    (add-to-list 'load-path *vterm*)
    (let (vterm-install)
      (require 'vterm))))

Editor

Here is the editor config, including some features and functions.

;;----------------------------------------------------------------------------
;; Editor
;;----------------------------------------------------------------------------

Diminish

(straight-use-package 'diminish)

FLX

(straight-use-package 'flx)

Advance Words Count

(straight-use-package '(advance-words-count :type git :host github :repo "LdBeth/advance-words-count.el"))

Anzu

(straight-use-package 'anzu)
(use-package anzu
  :defer    t
  :hook ((after-init . global-anzu-mode))
  :bind ([remap query-replace] . anzu-query-replace-regexp))

Auto Insert

(use-package autoinsert
  :init
  (define-auto-insert
    '("\\.py" . "Python Language")
    '("Python Language"
      "#!/usr/bin/env python3\n"
      "# -*- coding: utf-8 -*-\n"
      "r\"\"\"\n"
      "Life's pathetic, have fun (\"▔□▔)/hi~♡ Nasy.\n\n"
      "Excited without bugs::\n\n"
      "    |             *         *\n"
      "    |                  .                .\n"
      "    |           .\n"
      "    |     *                      ,\n"
      "    |                   .\n"
      "    |\n"
      "    |                               *\n"
      "    |          |\\___/|\n"
      "    |          )    -(             .              ·\n"
      "    |         =\\ -   /=\n"
      "    |           )===(       *\n"
      "    |          /   - \\\n"
      "    |          |-    |\n"
      "    |         /   -   \\     0.|.0\n"
      "    |  NASY___\\__( (__/_____(\\=/)__+1s____________\n"
      "    |  ______|____) )______|______|______|______|_\n"
      "    |  ___|______( (____|______|______|______|____\n"
      "    |  ______|____\\_|______|______|______|______|_\n"
      "    |  ___|______|______|______|______|______|____\n"
      "    |  ______|______|______|______|______|______|_\n"
      "    |  ___|______|______|______|______|______|____\n\n"
      "author   : Nasy https://nasy.moe\n"
      "date     : " (format-time-string "%b %e, %Y") \n
      "email    : Nasy <[email protected]>" \n
      "filename : " (file-name-nondirectory (buffer-file-name)) \n
      "project  : " (file-name-nondirectory (directory-file-name (or projectile-project-root default-directory))) \n
      "license  : GPL-3.0+\n\n"
      "At pick'd leisure\n"
      "  Which shall be shortly, single I'll resolve you,\n"
      "Which to you shall seem probable, of every\n"
      "  These happen'd accidents\n"
      "                          -- The Tempest\n"
      "\"\"\"\n"))

  (define-auto-insert
    '("\\.hs" . "Haskell Language")
    '("Haskell Language"
      "{-\n"
      " Excited without bugs, have fun (\"▔□▔)/hi~♡ Nasy.\n"
      " ------------------------------------------------\n"
      " |             *         *\n"
      " |                  .                .\n"
      " |           .\n"
      " |     *                      ,\n"
      " |                   .\n"
      " |\n"
      " |                               *\n"
      " |          |\\___/|\n"
      " |          )    -(             .              ·\n"
      " |         =\\ -   /=\n"
      " |           )===(       *\n"
      " |          /   - \\\n"
      " |          |-    |\n"
      " |         /   -   \\     0.|.0\n"
      " |  NASY___\\__( (__/_____(\\=/)__+1s____________\n"
      " |  ______|____) )______|______|______|______|_\n"
      " |  ___|______( (____|______|______|______|____\n"
      " |  ______|____\\_|______|______|______|______|_\n"
      " |  ___|______|______|______|______|______|____\n"
      " |  ______|______|______|______|______|______|_\n"
      " |  ___|______|______|______|______|______|____\n\n"
      " At pick'd leisure\n"
      "   Which shall be shortly, single I'll resolve you,\n"
      " Which to you shall seem probable, of every\n"
      "   These happen'd accidents\n"
      "                           -- The Tempest\n"
      "--------------------------------------------------------------------------------\n\n-}\n\n"
      "--------------------------------------------------------------------------------\n-- |\n"
      "-- Filename   : " (file-name-nondirectory (buffer-file-name)) \n
      "-- Project    : " (file-name-nondirectory (directory-file-name (or projectile-project-root default-directory))) \n
      "-- Author     : Nasy\n"
      "-- License    : GPL-3.0+\n--\n"
      "-- Maintainer : Nasy <[email protected]>\n"
      "--\n--\n--\n--------------------------------------------------------------------------------\n")))

Beacon (Disabled)

(use-package beacon
  :disabled t
  :straight t
  :init (setq beacon-size  7
              beacon-color "#f85e9f")
  :hook ((after-init . beacon-mode)))

Beginend

(straight-use-package 'beginend)
(use-package beginend
  :hook ((after-init . beginend-global-mode)))

Carbon Now sh

Emacs to carbon.now.sh integration.

https://github.com/veelenga/carbon-now-sh.el

Try: M-x carbon-now-sh RET

;; Emacs to carbon.now.sh integration
;; https://github.com/veelenga/carbon-now-sh.el
;; (carbon-now-sh)
(straight-use-package 'carbon-now-sh)

Cheat Sh

(straight-use-package 'cheat-sh)

Company

Company
(straight-use-package 'company)
(use-package company
  :init
  (gsetq company-minimum-prefix-length .2
         company-require-match 'company-explicit-action-p
         company-transformers '(company-sort-by-backend-importance)
         company-tooltip-align-annotations t
         company-dabbrev-other-buffers 'all
         company-dabbrev-downcase nil
         company-dabbrev-ignore-case t
         company-gtags-executable "gtags")
  :hook ((after-init . global-company-mode))
  :bind (("M-/"   . company-complete)
         ("C-M-/" . company-files)
         :map company-mode-map
         ("M-/"   . company-other-backend)
         :map company-active-map
         ("<tab>" . company-complete)
         ("M-/"   . company-other-backend)
         ("C-n"   . company-select-next)
         ("C-p"   . company-select-previous))
  :config
  (defvar my-prev-whitespace-mode nil)
  (make-variable-buffer-local 'my-prev-whitespace-mode)
  (defun pre-popup-draw ()
    "Turn off whitespace mode before showing company complete tooltip"
    (if whitespace-mode
        (progn
          (setq my-prev-whitespace-mode t)
          (whitespace-mode -1)
          (setq my-prev-whitespace-mode t))))
  (defun post-popup-draw ()
    "Restore previous whitespace mode after showing company tooltip"
    (if my-prev-whitespace-mode
        (progn
          (whitespace-mode 1)
          (setq my-prev-whitespace-mode nil))))
  (advice-add 'company-pseudo-tooltip-unhide :before #'pre-popup-draw)
  (advice-add 'company-pseudo-tooltip-hide :after #'post-popup-draw)

  (defun company-backend-with-yas (backends)
    "Add :with company-yasnippet to company BACKENDS.
  Taken from https://github.com/syl20bnr/spacemacs/pull/179."
    (if (and (listp backends) (memq 'company-yasnippet backends))
        backends
      (append (if (consp backends)
                  backends
                (list backends))
              '(:with company-yasnippet))))
  ;; add yasnippet to all backends
  (gsetq company-backends
         (mapcar #'company-backend-with-yas company-backends))
  :diminish company-mode)
Company Try Hard
(straight-use-package 'company-try-hard)
(use-package company-try-hard
  :bind (:map company-active-map
         ("C-z" . company-try-hard)))
Company Quickhelp
(straight-use-package 'company-quickhelp)
(use-package company-quickhelp
  :after company
  :bind (:map company-active-map
              ("C-c h" . company-quickhelp-manual-begin))
  :ghook #'after-init-hook
  :init (gsetq pos-tip-use-relative-coordinates t))
Company Math
(straight-use-package 'company-math)
Company Flx
(straight-use-package 'company-flx)
(use-package company-flx
  :after company
  :ghook #'after-init-hook)
Company Box
(when *c-box*
  (straight-use-package 'company-box)
  (use-package company-box
    :defer    t
    :after (all-the-icons company)
    :init
    (setq company-box-icons-alist 'company-box-icons-all-the-icons)
    :ghook 'company-mode-hook
    :config
    (setq company-box-backends-colors '((company-lsp      . "#e0f9b5")
                                        (company-elisp    . "#e0f9b5")
                                        (company-files    . "#ffffc2")
                                        (company-keywords . "#ffa5a5")
                                        (company-capf     . "#bfcfff")
                                        (company-dabbrev  . "#bfcfff")))
    (setq company-box-icons-unknown (concat (all-the-icons-material "find_in_page") " "))
    (setq company-box-icons-elisp
          (list
           (concat (all-the-icons-faicon "tag") " ")
           (concat (all-the-icons-faicon "cog") " ")
           (concat (all-the-icons-faicon "cube") " ")
           (concat (all-the-icons-material "color_lens") " ")))
    (setq company-box-icons-yasnippet (concat (all-the-icons-faicon "bookmark") " "))
    (setq company-box-icons-lsp
          `((1 .  ,(concat (all-the-icons-faicon   "text-height")    " ")) ;; Text
            (2 .  ,(concat (all-the-icons-faicon   "tags")           " ")) ;; Method
            (3 .  ,(concat (all-the-icons-faicon   "tag" )           " ")) ;; Function
            (4 .  ,(concat (all-the-icons-faicon   "tag" )           " ")) ;; Constructor
            (5 .  ,(concat (all-the-icons-faicon   "cog" )           " ")) ;; Field
            (6 .  ,(concat (all-the-icons-faicon   "cog" )           " ")) ;; Variable
            (7 .  ,(concat (all-the-icons-faicon   "cube")           " ")) ;; Class
            (8 .  ,(concat (all-the-icons-faicon   "cube")           " ")) ;; Interface
            (9 .  ,(concat (all-the-icons-faicon   "cube")           " ")) ;; Module
            (10 . ,(concat (all-the-icons-faicon   "cog" )           " ")) ;; Property
            (11 . ,(concat (all-the-icons-material "settings_system_daydream") " ")) ;; Unit
            (12 . ,(concat (all-the-icons-faicon   "cog" )           " ")) ;; Value
            (13 . ,(concat (all-the-icons-material "storage")        " ")) ;; Enum
            (14 . ,(concat (all-the-icons-material "closed_caption") " ")) ;; Keyword
            (15 . ,(concat (all-the-icons-faicon   "bookmark")       " ")) ;; Snippet
            (16 . ,(concat (all-the-icons-material "color_lens")     " ")) ;; Color
            (17 . ,(concat (all-the-icons-faicon   "file-text-o")    " ")) ;; File
            (18 . ,(concat (all-the-icons-material "refresh")        " ")) ;; Reference
            (19 . ,(concat (all-the-icons-faicon   "folder-open")    " ")) ;; Folder
            (20 . ,(concat (all-the-icons-material "closed_caption") " ")) ;; EnumMember
            (21 . ,(concat (all-the-icons-faicon   "square")         " ")) ;; Constant
            (22 . ,(concat (all-the-icons-faicon   "cube")           " ")) ;; Struct
            (23 . ,(concat (all-the-icons-faicon   "calendar")       " ")) ;; Event
            (24 . ,(concat (all-the-icons-faicon   "square-o")       " ")) ;; Operator
            (25 . ,(concat (all-the-icons-faicon   "arrows")         " "))) ;; TypeParameter
          )))

Dash

(straight-use-package 'dash)

Dash Functional

(straight-use-package 'dash-functional)

Dired

Dired
(use-package dired
  :init
  (let ((gls (executable-find "gls")))
    (when gls (setq insert-directory-program gls)))
  (setq dired-recursive-deletes 'top)
  :bind (:map dired-mode-map
              ([mouse-2] . dired-find-file             )
              ("C-c C-p" . wdired-change-to-wdired-mode)))
Diredfl
(straight-use-package 'diredfl)
(use-package diredfl
  :after dired
  :hook ((after-init . diredfl-global-mode)))
Uniquify
(use-package uniquify
  :init  ;; nicer naming of buffers for files with identical names
  (gsetq uniquify-buffer-name-style   'reverse
         uniquify-separator           " • "
         uniquify-after-kill-buffer-p t
         uniquify-ignore-buffers-re   "^\\*"))
Diff-hl (only for dired)
(straight-use-package 'diff-hl)
(use-package diff-hl
  :after dired
  :hook ((dired-mode . diff-hl-dired-mode)
         (magit-post-refresh . diff-hl-magit-post-refresh)))
Dired Hacks Utils
(straight-use-package 'dired-hacks-utils)
Dired Filter
(straight-use-package 'dired-filter)
(use-package dired-filter
  :after    dired
  :bind (:map dired-mode-map
              ("/" . dired-filter-map))
  :hook ((dired-mode . dired-filter-mode)
         (dired-mode . dired-filter-group-mode))
  :init (gsetq dired-filter-revert 'never
               dired-filter-group-saved-groups
               '(("default"
                  ("Git"
                   (directory . ".git")
                   (file . ".gitignore"))
                  ("Directory"
                   (directory))
                  ("PDF"
                   (extension . "pdf"))
                  ("LaTeX"
                   (extension "tex" "bib"))
                  ("Source"
                   (extension "c" "cpp" "hs" "rb" "py" "r" "cs" "el" "lisp" "html" "js" "css"))
                  ("Doc"
                   (extension "md" "rst" "txt"))
                  ("Org"
                   (extension . "org"))
                  ("Archives"
                   (extension "zip" "rar" "gz" "bz2" "tar"))
                  ("Images"
                   (extension "jpg" "JPG" "webp" "png" "PNG" "jpeg" "JPEG" "bmp" "BMP" "TIFF" "tiff" "gif" "GIF"))))))
Dired avfs
(when (executable-find "avfsd")
  (straight-use-package 'dired-avfs))
Dired Rainbow
(straight-use-package 'dired-rainbow)
(use-package dired-rainbow
  :after dired
  :config
  (dired-rainbow-define-chmod directory "#6cb2eb" "d.*")
  (dired-rainbow-define html        "#eb5286" ("css" "less" "sass" "scss" "htm" "html" "jhtm" "mht" "eml" "mustache" "xhtml"))
  (dired-rainbow-define xml         "#f2d024" ("xml" "xsd" "xsl" "xslt" "wsdl" "bib" "json" "msg" "pgn" "rss" "yaml" "yml" "rdata"))
  (dired-rainbow-define document    "#9561e2" ("docm" "doc" "docx" "odb" "odt" "pdb" "pdf" "ps" "rtf" "djvu" "epub" "odp" "ppt" "pptx"))
  (dired-rainbow-define markdown    "#ffed4a" ("org" "etx" "info" "markdown" "md" "mkd" "nfo" "pod" "rst" "tex" "textfile" "txt"))
  (dired-rainbow-define database    "#6574cd" ("xlsx" "xls" "csv" "accdb" "db" "mdb" "sqlite" "nc"))
  (dired-rainbow-define media       "#de751f" ("mp3" "mp4" "MP3" "MP4" "avi" "mpeg" "mpg" "flv" "ogg" "mov" "mid" "midi" "wav" "aiff" "flac"))
  (dired-rainbow-define image       "#f66d9b" ("tiff" "tif" "cdr" "gif" "ico" "jpeg" "jpg" "png" "psd" "eps" "svg"))
  (dired-rainbow-define log         "#c17d11" ("log"))
  (dired-rainbow-define shell       "#f6993f" ("awk" "bash" "bat" "sed" "sh" "zsh" "vim"))
  (dired-rainbow-define interpreted "#38c172" ("py" "ipynb" "rb" "pl" "t" "msql" "mysql" "pgsql" "sql" "r" "clj" "cljs" "scala" "js"))
  (dired-rainbow-define compiled    "#4dc0b5" ("asm" "cl" "lisp" "el" "c" "h" "c++" "h++" "hpp" "hxx" "m" "cc" "cs" "cp" "cpp" "go" "f" "for" "ftn" "f90" "f95" "f03" "f08" "s" "rs" "hi" "hs" "pyc" ".java"))
  (dired-rainbow-define executable  "#8cc4ff" ("exe" "msi"))
  (dired-rainbow-define compressed  "#51d88a" ("7z" "zip" "bz2" "tgz" "txz" "gz" "xz" "z" "Z" "jar" "war" "ear" "rar" "sar" "xpi" "apk" "xz" "tar"))
  (dired-rainbow-define packaged    "#faad63" ("deb" "rpm" "apk" "jad" "jar" "cab" "pak" "pk3" "vdf" "vpk" "bsp"))
  (dired-rainbow-define encrypted   "#ffed4a" ("gpg" "pgp" "asc" "bfe" "enc" "signature" "sig" "p12" "pem"))
  (dired-rainbow-define fonts       "#6cb2eb" ("afm" "fon" "fnt" "pfb" "pfm" "ttf" "otf"))
  (dired-rainbow-define partition   "#e3342f" ("dmg" "iso" "bin" "nrg" "qcow" "toast" "vcd" "vmdk" "bak"))
  (dired-rainbow-define vc          "#0074d9" ("git" "gitignore" "gitattributes" "gitmodules"))
  (dired-rainbow-define-chmod executable-unix "#38c172" "-.*x.*"))
Dired Subtree/ranger
(straight-use-package 'dired-subtree)

(straight-use-package 'dired-ranger)
Dired Narrow
(straight-use-package 'dired-narrow)
(use-package dired-narrow
  :after    dired
  :bind (:map dired-narrow-map
              ("<down>"  . dired-narrow-next-file)
              ("<up>"    . dired-narrow-previous-file)
              ("<right>" . dired-narrow-enter-directory)))
Dired Collapse
(straight-use-package 'dired-collapse)
(use-package dired-collapse
  :ghook 'dired-mode-hook)

Easy Kill

(straight-use-package 'easy-kill)
(use-package easy-kill
  :bind (([remap kill-ring-save] . easy-kill)
         ([remap mark-sexp]      . easy-mark)))
(straight-use-package 'thingopt)

Eldoc Box

Disabled by default due to it causes lots of cpu.

(when *eldoc-box*
  (straight-use-package 'eldoc-box)
  (use-package eldoc-box
    :hook ((eldoc-mode . eldoc-box-hover-mode)
           (eldoc-mode . eldoc-box-hover-at-point-mode))))

Fill Column

Unfill
(straight-use-package 'unfill)
(use-package unfill
  :bind (("M-q" . unfill-toggle)))
Visual-fill-column
(straight-use-package 'visual-fill-column)
(use-package visual-fill-column
  :preface
  (defun maybe-adjust-visual-fill-column ()
    "Readjust visual fill column when the global font size is modified.
This is helpful for writeroom-mode, in particular."
    (if visual-fill-column-mode
        (add-hook 'after-setting-font-hook 'visual-fill-column--adjust-window nil t)
      (remove-hook 'after-setting-font-hook 'visual-fill-column--adjust-window t)))
  :hook ((visual-line-mode        . visual-fill-column-mode        )
         (visual-fill-column-mode . maybe-adjust-visual-fill-column)))

Flycheck

(straight-use-package 'flycheck)
(straight-use-package 'flycheck-package)

(use-package flycheck
  :preface
  (defun save-buffer-maybe-show-errors ()
    "Save buffer and show errors if any."
    (interactive)
    (save-buffer)
    (when (not flycheck-current-errors)
      (flycheck-list-errors)))
  :commands (flycheck-mode
             flycheck-next-error
             flycheck-previous-error)
  ;; :bind (("C-x C-s" . save-buffer-maybe-show-errors))
  :hook ((after-init . global-flycheck-mode))
  :init (setq flycheck-display-errors-function
              #'flycheck-display-error-messages-unless-error-list)
  :config (defalias 'show-error-at-point-soon
            'flycheck-show-error-at-point)
  (add-to-list 'flycheck-emacs-lisp-checkdoc-variables 'sentence-end-double-space))


(use-package flycheck-package
  :after flycheck
  :init
  (with-eval-after-load 'elisp-mode
    (flycheck-package-setup)))

Grab Mac Link

(straight-use-package 'grab-mac-link)

Grep

(gsetq-default grep-highlight-matches t
               grep-scroll-output t)

(when *is-a-mac*
  (gsetq-default locate-command "mdfind"))

Highlight

cl-lib-highlight
(straight-use-package 'cl-lib-highlight)
(with-eval-after-load 'emacs-lisp-mode
  (use-package cl-lib-highlight
    :config
    (cl-lib-highlight-initialize)))
Color Identifiers Mode
(straight-use-package 'color-identifiers-mode)
(use-package color-identifiers-mode
  :defer t
  :hook ((prog-mode . color-identifiers-mode)))
hl-line
(straight-use-package 'hl-line)
(use-package hl-line
  :defer t
  :hook ((after-init . global-hl-line-mode)))
Highlight Indent Guides
(straight-use-package 'highlight-indent-guides)
(use-package highlight-indent-guides
  :init (gsetq highlight-indent-guides-responsive 'stack)
  :ghook '(prog-mode-hook text-mode-hook org-mode-hook))
Highlight Number
;; (straight-use-package 'highlight-numbers)
;; (use-package highlight-numbers
;;   :disabled t
;;   :ghook '(after-init-hook prog-mode-hook text-mode-hook org-mode-hook))
Rainbow-Mode
(straight-use-package 'rainbow-mode)
(use-package rainbow-mode
  :hook (((after-init
           text-mode
           org-mode
           css-mode
           html-mode
           prog-mode). rainbow-mode))
  :diminish rainbow-mode)

Helpful

https://github.com/Wilfred/helpful

(straight-use-package 'helpful)
(use-package helpful
  :bind (("C-c C-d" . helpful-at-point))
  :init (general-define-key
         :prefix "C-h"
         "f" 'helpful-callable
         "v" 'helpful-variable
         "k" 'helpful-key
         "F" 'helpful-function
         "C" 'helpful-command))

Helm

Helm
(straight-use-package 'helm)
(use-package helm-config
  :diminish helm-mode
  :commands nasy/helm
  :hook ((after-init . helm-mode)
         (after-init . helm-autoresize-mode))
  :init
  (gsetq helm-M-x-fuzzy-match        t
         helm-buffers-fuzzy-matching t
         helm-recentf-fuzzy-match    t
         helm-imenu-fuzzy-match      t
         helm-locate-fuzzy-match     t
         helm-apropos-fuzzy-match    t
         helm-lisp-fuzzy-completion  t
         helm-allow-mouse            t
         helm-follow-mode-persistent t
         helm-ff-lynx-style-map      t)

  (when (executable-find "curl")
    (gsetq helm-google-suggest-use-curl-p t))

  (gsetq helm-split-window-in-side-p           t
         helm-move-to-line-cycle-in-source     nil
         helm-ff-search-library-in-sexp        t
         helm-scroll-amount                    8
         helm-ff-file-name-history-use-recentf t
         helm-echo-input-in-header-line        t
         helm-source-names-using-follow        '("Buffers" "kill-buffer" "Occur"))

  (gsetq helm-grep-ag-command
         "rg --color=always --colors 'match:fg:black' --colors 'match:bg:yellow' --smart-case --no-heading --line-number %s %s %s"
         helm-grep-ag-pipe-cmd-switches
         '("--colors 'match:fg:black'" "--colors 'match:bg:yellow'"))

  (general-define-key
   "M-x"     'helm-M-x
   "M-y"     'helm-show-kill-ring
   "M-b"     'nasy/helm
   "C-o"     'helm-occur
   "C-s"     'helm-occur
   "C-x C-f" 'helm-find-files)
  (general-define-key
   :prefix "C-x c"
   "x"   'helm-register
   "g"   'helm-google-suggest
   "M-:" 'helm-eval-expression-with-eldoc)
  (general-define-key
   :keymaps 'helm-map
   "<tab>" 'helm-execute-persistent-action ; rebind tab to run persistent action
   "C-i"   'helm-execute-persistent-action ; make TAB works in terminal
   "C-z"   'helm-select-action) ; list actions using C-z
  (general-define-key
   :keymaps 'shell-mode-map
   "C-c C-l" 'helm-comint-input-ring)
  (general-define-key
   :keymaps 'minibuffer-local-map
   "C-c C-l" 'helm-minibuffer-history)

  :config
  (add-to-list 'helm-sources-using-default-as-input 'helm-source-man-pages)

  (require 'helm-buffers)
  (require 'helm-for-files)

  (defun nasy/helm ()
    (interactive)
    (let ((helm-ff-transformer-show-only-basename nil)
          helm-source-list)
      (unless helm-source-buffers-list
        (setq helm-source-buffers-list
              (helm-make-source "Buffers" 'helm-source-buffers)))
      (cond (
             ;; Just add helm-source-projectile-* in list when current place in project.
             (projectile-project-p)
             (setq helm-source-list
                   '(
                     ;; helm-source-awesome-tab-group
                     helm-source-projectile-buffers-list
                     helm-source-buffers-list
                     helm-source-recentf
                     helm-source-projectile-files-list)))

            (t
             (setq helm-source-list
                   '(
                     ;; helm-source-awesome-tab-group
                     helm-source-buffers-list
                     helm-source-recentf))))
      (helm-other-buffer helm-source-list "*helm search*"))))
Helm Org
(use-package helm-org
  :defer t
  :config
  (cl-defun helm-org-headings-in-buffer ()
    (interactive)
    (helm :sources (helm-source-org-headings-for-files
                    (list (projectile-completing-read
                           "File to look at headings from: "
                           (projectile-all-project-files))))
          :candidate-number-limit 99999
          :buffer "*helm org inbuffer*")))
Helm Company
(straight-use-package 'helm-company)
(use-package helm-company
  :defer t
  :bind (:map
         company-mode-map ("C-:" . helm-company)
         :map
         company-active-map ("C-:" . helm-company)))
Helm Shell
(use-package helm-eshell
  :defer t
  :bind (:map eshell-mode-map
              ("C-c C-l" . helm-eshell-history)))
Helm Descbings
(straight-use-package 'helm-descbinds)
(use-package helm-descbinds
  :defer t
  :hook ((after-init . helm-descbinds-mode)))
Helm Projectile
(straight-use-package 'helm-projectile)
(use-package helm-projectile
  :defer t
  :hook ((after-init . helm-projectile-on))
  :init (gsetq projectile-completion-system 'helm))
Helm Ag
(straight-use-package 'helm-ag)
(use-package helm-ag
  :defer t
  :init (gsetq  ;; brew install rg
         helm-ag-base-command         "rg --no-heading --smart-case"
         helm-ag-fuzzy-match          t
         helm-ag-use-grep-ignore-list t
         helm-ag-use-agignore         t))
Helm Dash
(straight-use-package 'helm-dash)
(use-package helm-dash
  :defer t
  :init (gsetq helm-dash-docsets-path "~/.docsets"))
Helm Ls Git
(straight-use-package 'helm-ls-git)
(use-package helm-ls-git
  :defer t
  :bind (("C-<f6>"   . helm-ls-git-ls)
         ("C-x g"    . helm-ls-git-ls)
         ("C-x C-d"  . helm-browse-project)))

Htmlize

(straight-use-package 'htmlize)
(use-package htmlize
  :defer t
  :init (gsetq htmlize-pre-style t))

Hydra

(straight-use-package 'hydra)
(use-package hydra
  :defer t
  :config
  (general-define-key
   :prefix "C-x"
   "9" 'hydra-unicode/body)
  (general-define-key
   :keymaps 'dired-mode-map
   "." 'hydra-dired/body)
  ;; insert unicode
  (defun nasy:insert-unicode (unicode-name)
    "Same as C-x 8 enter UNICODE-NAME."
    (insert-char (gethash unicode-name (ucs-names))))
  (defhydra hydra-unicode (:hint nil)
    "
    Unicode  _e_ €  _s_ ZERO WIDTH SPACE
             _f_ ♀  _o_ °   _m_ µ
             _r_ ♂  _a_ →   _l_ λ
    "
    ("e" (nasy:insert-unicode "EURO SIGN"))
    ("r" (nasy:insert-unicode "MALE SIGN"))
    ("f" (nasy:insert-unicode "FEMALE SIGN"))
    ("s" (nasy:insert-unicode "ZERO WIDTH SPACE"))
    ("o" (nasy:insert-unicode "DEGREE SIGN"))
    ("a" (nasy:insert-unicode "RIGHTWARDS ARROW"))
    ("m" (nasy:insert-unicode "MICRO SIGN"))
    ("l" (nasy:insert-unicode "GREEK SMALL LETTER LAMBDA")))


  (defhydra hydra-dired (:hint nil :color pink)
    "
  _+_ mkdir          _v_iew           _m_ark             _(_ details        _i_nsert-subdir    wdired
  _C_opy             _O_ view other   _U_nmark all       _)_ omit-mode      _$_ hide-subdir    C-x C-q : edit
  _D_elete           _o_pen other     _u_nmark           _l_ redisplay      _w_ kill-subdir    C-c C-c : commit
  _R_ename           _M_ chmod        _t_oggle           _g_ revert buf     _e_ ediff          C-c ESC : abort
  _Y_ rel symlink    _G_ chgrp        _E_xtension mark   _s_ort             _=_ pdiff
  _S_ymlink          ^ ^              _F_ind marked      _._ toggle hydra   \\ flyspell
  _r_sync            ^ ^              ^ ^                ^ ^                _?_ summary
  _z_ compress-file  _A_ find regexp
  _Z_ compress       _Q_ repl regexp

  T - tag prefix
  "
    ("\\" dired-do-ispell)
    ("(" dired-hide-details-mode)
    (")" dired-omit-mode)
    ("+" dired-create-directory)
    ("=" diredp-ediff)         ;; smart diff
    ("?" dired-summary)
    ("$" diredp-hide-subdir-nomove)
    ("A" dired-do-find-regexp)
    ("C" dired-do-copy)        ;; Copy all marked files
    ("D" dired-do-delete)
    ("E" dired-mark-extension)
    ("e" dired-ediff-files)
    ("F" dired-do-find-marked-files)
    ("G" dired-do-chgrp)
    ("g" revert-buffer)        ;; read all directories again (refresh)
    ("i" dired-maybe-insert-subdir)
    ("l" dired-do-redisplay)   ;; relist the marked or singel directory
    ("M" dired-do-chmod)
    ("m" dired-mark)
    ("O" dired-display-file)
    ("o" dired-find-file-other-window)
    ("Q" dired-do-find-regexp-and-replace)
    ("R" dired-do-rename)
    ("r" dired-do-rsynch)
    ("S" dired-do-symlink)
    ("s" dired-sort-toggle-or-edit)
    ("t" dired-toggle-marks)
    ("U" dired-unmark-all-marks)
    ("u" dired-unmark)
    ("v" dired-view-file)      ;; q to exit, s to search, = gets line #
    ("w" dired-kill-subdir)
    ("Y" dired-do-relsymlink)
    ("z" diredp-compress-this-file)
    ("Z" dired-do-compress)
    ("q" nil)
    ("." nil :color blue)))

iBuffer

ibuffer
(use-package ibuffer
  :bind (("C-x C-b" . ibuffer))
  :init
  (gsetq ibuffer-saved-filter-groups
         '(("Normal"
            ("Dired"      (mode . dired-mode))
            ("Emacs"     (or
                          (name . "^\\*dashboard\\*$" )
                          (name . "^\\*scratch\\*$"   )
                          (name . "^\\*Messages\\*$"  )
                          (name . "^\\*Backtrace\\*$" )))
            ("Term"       (mode . vterm-mode))
            ("Text"      (or
                          (mode . org-mode)
                          (mode . markdown)
                          (mode . rst-mode)
                          (mode . text-mode)))
            ("TeX"        (mode . tex-mode))
            ("Languages" (or
                          (mode . emacs-lisp-mode)
                          (mode . haskell-mode)
                          (mode . javascript-mode)
                          (mode . lisp-mode)
                          (mode . python-mode)
                          (mode . ruby-mode)
                          (mode . rust-mode)
                          (mode . html-mode)
                          (mode . css-mode)
                          (mode . prog-mode)))
            ("GNUs"      (or
                          (mode . message-mode)
                          (mode . bbdb-mode)
                          (mode . mail-mode)
                          (mode . gnus-group-mode)
                          (mode . gnus-summary-mode)
                          (mode . gnus-article-mode)
                          (name . "^\\.bbdb$")
                          (name . "^\\.newsrc-dribble")))
            ("Magit"      (name . "^magit"))
            ("Help"      (or
                          (name . "^\\*Help\\*$")
                          (name . "^\\*Apropos\\*$")
                          (name . "^\\*info\\*$")
                          (name . "^\\*helpful")))
            ("Custom"    (or
                          (mode . custom-mode)
                          (name . "^\\*Customize")))
            ("Helm"       (mode . helm-major-mode))
            ))
         ibuffer-show-empty-filter-groups nil
         ibuffer-default-sorting-mode     'filename/process)
  :hook ((ibuffer-mode . (lambda () (ibuffer-switch-to-saved-filter-groups "Normal")))))
ibuffer vc
(straight-use-package 'ibuffer-vc)
Other settings
(use-package ibuffer
  :defer t
  :config
  (define-ibuffer-column size-h
    (:name "Size" :inline t)
    (file-size-human-readable (buffer-size)))
  (setq
   ibuffer-formats
   '((mark modified read-only vc-status-mini " "
           (name 22 22 :left :elide)
           " "
           (size-h 9 -1 :right)
           " "
           (mode 12 12 :left :elide)
           " "
           vc-relative-file)
     (mark modified read-only vc-status-mini " "
           (name 22 22 :left :elide)
           " "
           (size-h 9 -1 :right)
           " "
           (mode 14 14 :left :elide)
           " "
           (vc-status 12 12 :left)
           " "
           vc-relative-file))))

imenu list

(straight-use-package 'imenu-list)
(use-package imenu-list
  :bind (("C-." . imenu-list-smart-toggle))
  :init (setq imenu-list-auto-resize t))

indent-tools

(straight-use-package 'indent-tools)
(use-package indent-tools
  :bind (("C-c TAB" . indent-tools-hydra/body)))

iSearch

I only use rg to search, so I disabled the key-map of isearch.

(use-package isearch
  :preface
  ;; Search back/forth for the symbol at point
  ;; See http://www.emacswiki.org/emacs/SearchAtPoint
  (defun isearch-yank-symbol ()
    "*Put symbol at current point into search string."
    (interactive)
    (let ((sym (thing-at-point 'symbol)))
      (if sym
          (progn
            (setq isearch-regexp t
                  isearch-string (concat "\\_<" (regexp-quote sym) "\\_>")
                  isearch-message (mapconcat 'isearch-text-char-description isearch-string "")
                  isearch-yank-flag t))
        (ding)))
    (isearch-search-and-update))

  ;; http://www.emacswiki.org/emacs/ZapToISearch
  (defun isearch-exit-other-end (rbeg rend)
    "Exit isearch, but at the other end of the search string.
This is useful when followed by an immediate kill."
    (interactive "r")
    (isearch-exit)
    (goto-char isearch-other-end))

  :bind (:map isearch-mode-map
              ([remap isearch-delete-char] . isearch-del-char)
              ("C-M-w"                     . isearch-yank-symbol)
              ([(control return)]              . isearch-exit-other-end)
              ("C-c C-o"                   . isearch-occur)))

Ivy, Counsel and Swiper

Now disabled.

Large File

(straight-use-package 'vlf)
(use-package vlf
  :init
  (defun ffap-vlf ()
    "Find file at point with VLF."
    (interactive)
    (let ((file (ffap-file-at-point)))
      (unless (file-exists-p file)
        (error "File does not exist: %s" file))
      (vlf file))))

Link Hint

(straight-use-package 'link-hint)
(use-package link-hint
  :bind (("C-c l o" . link-hint-open-link)
         ("C-c l c" . link-hint-copy-link))
  :config
  (general-define-key
   :prefix "C-c l")
  "o" 'link-hint-open-link
  "c" 'link-hint-copy-link)

List Unicode Display

(straight-use-package 'list-unicode-display)

mmm-mode

(straight-use-package 'mmm-mode)
(use-package mmm-auto
  :init (gsetq
         mmm-global-mode
         'buffers-with-submode-classes
         mmm-submode-decoration-level 2))

Multiple Cursors

(straight-use-package 'multiple-cursors)
(use-package multiple-cursors
  :bind (("C-<"     . mc/mark-previous-like-this)
         ("C->"     . mc/mark-next-like-this)
         ("C-+"     . mc/mark-next-like-this)
         ("C-c C-<" . mc/mark-all-like-this))
  :config
  ;; From active region to multiple cursors:
  (general-define-key
   :preface "C-c m"
   "r" 'set=rectangular-region-anchor
   "c" 'mc/edit-lines
   "e" 'mc/edit-ends-of-lines
   "a" 'mc/edit-beginnings-of-lines))

Pangu Spacing

(straight-use-package 'pangu-spacing)
(use-package pangu-spacing
  :init (gsetq pangu-spacing-real-insert-separtor t)
  :hook ((after-init . global-pangu-spacing-mode)))

Paper Break Lines

(straight-use-package 'page-break-lines)
(use-package page-break-lines
  :hook ((after-init . global-page-break-lines-mode))
  :diminish page-break-lines-mode)

Parens

I use smartparens, parinfer with rainbow-delimiters instead of paredit.

(add-hook 'after-init-hook 'show-paren-mode)
Smartparens
(straight-use-package 'smartparens)
(use-package smartparens-config
  :hook ((after-init . show-smartparens-global-mode)
         (after-init . smartparens-global-mode))
  :init (gsetq sp-hybrid-kill-entire-symbol nil))
Parinfer
(straight-use-package 'parinfer)
(use-package parinfer
  :bind (("C-," . parinfer-toggle-mode))
  :init (gsetq parinfer-extensions
               '(defaults       ; should be included.
                 pretty-parens  ; different paren styles for different modes.
                 ;; evil           ; If you use Evil.
                 ;; lispy          ; If you use Lispy. With this extension, you should install Lispy and do not enable lispy-mode directly.
                 ;; paredit        ; Introduce some paredit commands.
                 smart-tab      ; C-b & C-f jump positions and smart shift with tab & S-tab.
                 smart-yank))   ; Yank behavior depend on mode.
  :ghook lisp-modes-hooks)
Rainbow Delimiters
(straight-use-package 'rainbow-delimiters)
(use-package rainbow-delimiters
  :ghook '(prog-mode-hook text-mode-hook org-src-mode-hook))
Highlight Parentheses
(straight-use-package 'highlight-parentheses)
(use-package highlight-parentheses
  :init (gsetq hl-paren-highlight-adjacent t)
  :hook ((after-init . global-highlight-parentheses-mode)))

PDF Tools

(straight-use-package 'pdf-tools)
(use-package pdf-tools
  :defer t
  :config
  (gsetq-default pdf-view-display-size 'fit-width)
  (bind-keys :map pdf-view-mode-map
             ("\\" . hydra-pdftools/body)
             ("<s-spc>" .  pdf-view-scroll-down-or-next-page)
             ("g"  . pdf-view-first-page)
             ("G"  . pdf-view-last-page)
             ("l"  . image-forward-hscroll)
             ("h"  . image-backward-hscroll)
             ("j"  . pdf-view-next-page)
             ("k"  . pdf-view-previous-page)
             ("e"  . pdf-view-goto-page)
             ("u"  . pdf-view-revert-buffer)
             ("al" . pdf-annot-list-annotations)
             ("ad" . pdf-annot-delete)
             ("aa" . pdf-annot-attachment-dired)
             ("am" . pdf-annot-add-markup-annotation)
             ("at" . pdf-annot-add-text-annotation)
             ("y"  . pdf-view-kill-ring-save)
             ("i"  . pdf-misc-display-metadata)
             ("s"  . pdf-occur)
             ("b"  . pdf-view-set-slice-from-bounding-box)
             ("r"  . pdf-view-reset-slice)))

Pretty

Pretty Mode
(straight-use-package 'pretty-mode)
(use-package pretty-mode
  :commands (turn-on-pretty-mode global-prettify-symbols-mode)
  :hook (((text-mode
           org-mode)  . turn-on-pretty-mode)
         (after-init  . global-prettify-symbols-mode)
         (prog-mode . (lambda () (mapc (lambda (pair) (push pair prettify-symbols-alist))
                                  '(;; Data Type             P N
                                    ("Float"  . #x211d)  ;; ℝxxxx
                                    ("float"  . #x211d)  ;; ℝxxx
                                    ("Int"    . #x2124)  ;; ℤxxx
                                    ("int"    . #x2124)  ;; 𝕫xxx
                                    ;; ("String" . #x1d57e)  ;; 𝕊 𝕾
                                    ;; ("string" . #x1d598)  ;; 𝕤 𝖘
                                    ;; ("str"    . #x1d598)  ;; 𝕤 𝖘
                                    ("String" . (#x1d54a (Br . Bl) #x2006))  ;; 𝕊 xxxxxx
                                    ("string" . (#x1d564 (Br . Bl) #x2006))  ;; 𝕤 xxxxxx
                                    ("str"    . (#x1d564 (Br . Bl) #x2006))  ;; 𝕤 xxxx
                                    ("Char"   . #x2102)   ;; ℂx
                                    ("char"   . (#x1d554 (Br . Bl) #x2006))  ;; 𝕔 x

                                    ("False"  . #x1d53d)  ;; 𝕱 𝔽
                                    ("True"   . #x1d54b)  ;; 𝕿 𝕋

                                    ("Any"    . #x2203)  ;; 
                                    ("any"    . #x2203)  ;; 
                                    ("any_"   . #x2203)  ;; 
                                    ("And"    . #x22c0)  ;; 
                                    ("and"    . #x22cf)  ;; 
                                    ("Or"     . #x22c1)  ;; 
                                    ("or"     . #x22cE)  ;; 
                                    ("not"    . #x00ac)  ;; ¬
                                    ("not_"   . #x00ac)  ;; ¬

                                    ("All"    . #x2200)  ;; 
                                    ("all"    . #x2200)  ;; 
                                    ("all_"   . #x2200)  ;; 
                                    ("for"    . #x2200)  ;; 
                                    ("forall" . #x2200)  ;; 
                                    ("forM"   . #x2200)  ;; 

                                    ("pi"     . #x03c0)  ;; π

                                    ("sum"    . #x2211)  ;; 
                                    ("Sum"    . #x2211)  ;; 
                                    ("Product" . #x220F) ;; 
                                    ("product" . #x220F) ;; 

                                    ("None"   . #x2205)  ;; 
                                    ("none"   . #x2205)  ;; 

                                    ("in"     . #x2286)  ;; 
                                    ("`elem`" . #x2286)  ;; 
                                    ("not in"    . #x2288)  ;; 
                                    ("`notElem`" . #x2288)  ;; 

                                    ("return" . (#x21d2 (Br . Bl) #x2006 (Br . Bl) #x2004))  ;; ⇒  x
                                    ("yield"  . (#x21d4 (Br . Bl) #x2004))  ;; ⇔ x
                                    ("pure"   . (#x21f0 (Br . Bl)))))))          ;; ⇰ x

         ((prog-mode
           emacs-lisp-mode
           org-mode) . (lambda () (mapc (lambda (pair) (push pair prettify-symbols-alist))
                                   '(;; Global
                                     ;; Pipes
                                     ("<|"  . (?\s (Br . Bl) #Xe14d))
                                     ("<>"  . (?\s (Br . Bl) #Xe15b))
                                     ("<|>" . (?\s (Br . Bl) ?\s (Br . Bl) #Xe14e))
                                     ("|>"  . (?\s (Br . Bl) #Xe135))

                                     ;; Brackets
                                     ("<*"  . (?\s (Br . Bl) #Xe14b))
                                     ("<*>" . (?\s (Br . Bl) ?\s (Br . Bl) #Xe14c))
                                     ("*>"  . (?\s (Br . Bl) #Xe104))
                                     ("<$"  . (?\s (Br . Bl) #Xe14f))
                                     ("<$>" . (?\s (Br . Bl) ?\s (Br . Bl) #Xe150))
                                     ("$>"  . (?\s (Br . Bl) #Xe137))
                                     ("<+"  . (?\s (Br . Bl) #Xe155))
                                     ("<+>" . (?\s (Br . Bl) ?\s (Br . Bl) #Xe156))
                                     ("+>"  . (?\s (Br . Bl) #Xe13a))
                                     ("[]"  . (#x2005 (Br . Bl) #x1d731 (Br . Bl) #x2005))

                                     ;; Equality
                                     ("=/="  . (?\s (Br . Bl) ?\s (Br . Bl) #Xe143))
                                     ("/="   . (?\s (Br . Bl) #Xe12c))
                                     ("/=="  . (?\s (Br . Bl) ?\s (Br . Bl) #Xe12d))
                                     ("/==>" . (?\s (Br . Bl) ?\s (Br . Bl) ?\s (Br . Bl) #Xe13c))
                                     ("!==>" . (?\s (Br . Bl) ?\s (Br . Bl) ?\s (Br . Bl) #Xe13c))
                                     ;; Special
                                     ("||="  . (?\s (Br . Bl) ?\s (Br . Bl) #Xe133))
                                     ("|="   . (?\s (Br . Bl) #Xe134))
                                     ("~="   . (?\s (Br . Bl) #Xe166))
                                     ("^="   . (?\s (Br . Bl) #Xe136))
                                     ("=:="  . (?\s (Br . Bl) ?\s (Br . Bl) #Xe13b))

                                     ;; Comparisons
                                     ("</"   . (?\s (Br . Bl) #Xe162))
                                     ("</>"  . (?\s (Br . Bl) ?\s (Br . Bl) #Xe163))

                                     ;; Shifts
                                     ("=>>"  . (?\s (Br . Bl) ?\s (Br . Bl) #Xe147))
                                     ("->>"  . (?\s (Br . Bl) ?\s (Br . Bl) #Xe147))
                                     (">>>"  . (?\s (Br . Bl) ?\s (Br . Bl) #Xe14a))
                                     (">>>"  . (?\s (Br . Bl) ?\s (Br . Bl) #Xe14a))
                                     ("=<<"  . (?\s (Br . Bl) ?\s (Br . Bl) #Xe15c))
                                     ("-<<"  . (?\s (Br . Bl) ?\s (Br . Bl) #Xe15c))
                                     ("<<<"  . (?\s (Br . Bl) ?\s (Br . Bl) #Xe15f))

                                     ;; Dots
                                     (".-"   . (?\s (Br . Bl) #Xe122))
                                     (".="   . (?\s (Br . Bl) #Xe123))
                                     ("..<"  . (?\s (Br . Bl) ?\s (Br . Bl) #Xe125))

                                     ;; Hashes
                                     ("#{"   . (?\s (Br . Bl) #Xe119))
                                     ("#("   . (?\s (Br . Bl) #Xe11e))
                                     ("#_"   . (?\s (Br . Bl) #Xe120))
                                     ("#_("  . (?\s (Br . Bl) #Xe121))
                                     ("#?"   . (?\s (Br . Bl) #Xe11f))
                                     ("#["   . (?\s (Br . Bl) #Xe11a))

                                     ;; REPEATED CHARACTERS
                                     ;; 2-Repeats
                                     ("!!"   . (?\s (Br . Bl) #Xe10d))
                                     ("%%"   . (?\s (Br . Bl) #Xe16a))

                                     ;; 2+3-Repeats
                                     ("##"   . (?\s (Br . Bl) #Xe11b))
                                     ("###"  . (?\s (Br . Bl) ?\s (Br . Bl) #Xe11c))
                                     ("####" . (?\s (Br . Bl) ?\s (Br . Bl) #Xe11d))
                                     ("---"  . (?\s (Br . Bl) ?\s (Br . Bl) #Xe112))
                                     ("{-"   . (?\s (Br . Bl) #Xe108))
                                     ("-}"   . (?\s (Br . Bl) #Xe110))
                                     ("\\\\" . (?\s (Br . Bl) #Xe106))
                                     ("\\\\\\" . (?\s (Br . Bl) ?\s (Br . Bl) #Xe107))
                                     (".."   . (?\s (Br . Bl) #Xe124))
                                     ("..."  . (?\s (Br . Bl) ?\s (Br . Bl) #Xe126))
                                     ("+++"  . (?\s (Br . Bl) ?\s (Br . Bl) #Xe139))
                                     ("//"   . (?\s (Br . Bl) #Xe12f))
                                     ("///"  . (?\s (Br . Bl) ?\s (Br . Bl) #Xe130))
                                     ("::"   . (?\s (Br . Bl) #Xe10a))  ;; 
                                     (":::"  . (?\s (Br . Bl) ?\s (Br . Bl) #Xe10b))

                                     ;; Arrows
                                     ;; Direct
                                     ;; ("->"  . (?\s (Br . Bl) #Xe114))  ;; 
                                     ;; ("=>"  . (?\s (Br . Bl) #Xe13f))
                                     ("->>" . (?\s (Br . Bl) ?\s (Br . Bl) #Xe115))
                                     ("=>>" . (?\s (Br . Bl) ?\s (Br . Bl) #Xe140))
                                     ("<<-" . (?\s (Br . Bl) ?\s (Br . Bl) #Xe15d))
                                     ("<<=" . (?\s (Br . Bl) ?\s (Br . Bl) #Xe15e))
                                     ("<->" . (?\s (Br . Bl) ?\s (Br . Bl) #Xe154))
                                     ("<=>" . (?\s (Br . Bl) ?\s (Br . Bl) #Xe159))
                                     ;; Branches
                                     ("-<"  . (?\s (Br . Bl) #Xe116))
                                     ("-<<" . (?\s (Br . Bl) ?\s (Br . Bl) #Xe117))
                                     (">-"  . (?\s (Br . Bl) #Xe144))
                                     (">>-" . (?\s (Br . Bl) ?\s (Br . Bl) #Xe148))
                                     ("=<<" . (?\s (Br . Bl) ?\s (Br . Bl) #Xe142))
                                     (">=>" . (?\s (Br . Bl) ?\s (Br . Bl) #Xe146))
                                     (">>=" . (?\s (Br . Bl) ?\s (Br . Bl) #Xe149))
                                     ("<=<" . (?\s (Br . Bl) ?\s (Br . Bl) #Xe15a))
                                     ;; Squiggly
                                     ("<~"  . (?\s (Br . Bl) #Xe160))
                                     ("<~~" . (?\s (Br . Bl) ?\s (Br . Bl) #Xe161))
                                     ("~>"  . (?\s (Br . Bl) #Xe167))
                                     ("~~>" . (?\s (Br . Bl) ?\s (Br . Bl) #Xe169))
                                     ("-~"  . (?\s (Br . Bl) #Xe118))
                                     ("~-"  . (?\s (Br . Bl) #Xe165))

                                     ;; MISC
                                     ("www" . (?\s (Br . Bl) ?\s (Br . Bl) #Xe100))
                                     ("[email protected]"  . (?\s (Br . Bl) #Xe164))
                                     ("~~"  . (?\s (Br . Bl) #Xe168))
                                     ("?="  . (?\s (Br . Bl) #Xe127))
                                     (":="  . (?\s (Br . Bl) #Xe10c))
                                     ("/>"  . (?\s (Br . Bl) #Xe12e))
                                     ("+"   . #Xe16d)
                                     ("(:"  . (?\s (Br . Bl) #Xe16c))))))


         (python-mode . (lambda ()
                          (mapc (lambda (pair) (push pair prettify-symbols-alist))
                                '(;; Syntax
                                  ;;("def"    . (#x1d521 (Br . Bl) #x1d522 (Br . Bl) #x1d523))
                                  ("def"    . #x1D487)  ;; 𝒇 1 111
                                  ("List"   . #x1d543)  ;; 𝕃 𝕷
                                  ("list"   . (#x1d55d (Br . Bl) #x2006 (Br . Bl) #x2005))  ;; 𝕝   𝖑
                                  ("Dict"   . #x1d53B)  ;; 𝔻 𝕯
                                  ("dict"   . #x1d555)  ;; 𝕕 𝖉
                                  ("Set"    . #x1d61a)  ;; 𝔖 𝘚
                                  ("set"    . #x1d634)  ;; 𝔰 𝘴
                                  ("Tuple"  . #x1d61b)  ;; 𝕋 𝕿 𝘛
                                  ("tuple"  . #x1d635)  ;; 𝕥 𝖙 𝘵

                                  ("Union"  . #x22c3)  ;; 
                                  ("union"  . #x22c3)))))  ;; 

         (haskell-mode . (lambda ()
                           (mapc (lambda (pair) (push pair prettify-symbols-alist))
                                 '(;; Syntax
                                   ("pure" . (#x21f0 (Br . Bl) #x2006))))))) ;; ⇰  x
                                   ;; (" . "  . (?\s (Br . Bl) #x2218 (Br . Bl) ?\s (Br . Bl) #x2006)) ;; ∘

  :config
  (pretty-activate-groups
   '(:sub-and-superscripts :greek :arithmetic))

  (pretty-deactivate-groups
   '(:equality :ordering :ordering-double :ordering-triple
               :arrows :arrows-twoheaded :punctuation
               :logic :sets :arithmetic-double :arithmetic-triple)))
ipretty
(straight-use-package 'ipretty)
(use-package ipretty
  :defer    t
  :ghook 'after-init-hook)
Pretty Font
;; https://github.com/tonsky/FiraCode/wiki/Emacs-instructions
;; This works when using emacs --daemon + emacsclient
(add-hook 'after-make-frame-functions (lambda (frame) (set-fontset-font t '(#Xe100 . #Xe16f) "Fira Code Symbol")))
;; This works when using emacs without server/client
(set-fontset-font t '(#Xe100 . #Xe16f) "Fira Code Symbol")
;; I haven't found one statement that makes both of the above situations work, so I use both for now

(defun pretty-fonts-set-fontsets (CODE-FONT-ALIST)
  "Utility to associate many unicode points with specified `CODE-FONT-ALIST'."
  (--each CODE-FONT-ALIST
    (-let (((font . codes) it))
      (--each codes
        (set-fontset-font nil `(,it . ,it) font)
        (set-fontset-font t `(,it . ,it) font)))))

(defun pretty-fonts--add-kwds (FONT-LOCK-ALIST)
  "Exploits `font-lock-add-keywords'(`FONT-LOCK-ALIST') to apply regex-unicode replacements."
  (font-lock-add-keywords
   nil (--map (-let (((rgx uni-point) it))
               `(,rgx (0 (progn
                           (compose-region
                            (match-beginning 1) (match-end 1)
                            ,(concat "\t" (list uni-point)))
                           nil))))
             FONT-LOCK-ALIST)))

(defmacro pretty-fonts-set-kwds (FONT-LOCK-HOOKS-ALIST)
  "Set regex-unicode replacements to many modes(`FONT-LOCK-HOOKS-ALIST')."
  `(--each ,FONT-LOCK-HOOKS-ALIST
     (-let (((font-locks . mode-hooks) it))
       (--each mode-hooks
         (add-hook it (-partial 'pretty-fonts--add-kwds
                                (symbol-value font-locks)))))))

(defconst pretty-fonts-fira-font
  '(;; OPERATORS
    ;; Pipes
    ("\\(<|\\)" #Xe14d) ("\\(<>\\)" #Xe15b) ("\\(<|>\\)" #Xe14e) ("\\(|>\\)" #Xe135)

    ;; Brackets
    ("\\(<\\*\\)" #Xe14b) ("\\(<\\*>\\)" #Xe14c) ("\\(\\*>\\)" #Xe104)
    ("\\(<\\$\\)" #Xe14f) ("\\(<\\$>\\)" #Xe150) ("\\(\\$>\\)" #Xe137)
    ("\\(<\\+\\)" #Xe155) ("\\(<\\+>\\)" #Xe156) ("\\(\\+>\\)" #Xe13a)

    ;; Equality
    ("\\(!=\\)" #Xe10e) ("\\(!==\\)"         #Xe10f) ("\\(=/=\\)" #Xe143)
    ("\\(/=\\)" #Xe12c) ("\\(/==\\)"         #Xe12d)
    ("\\(===\\)" #Xe13d) ("[^!/]\\(==\\)[^>]" #Xe13c)

    ;; Equality Special
    ("\\(||=\\)"  #Xe133) ("[^|]\\(|=\\)" #Xe134)
    ("\\(~=\\)"   #Xe166)
    ("\\(\\^=\\)" #Xe136)
    ("\\(=:=\\)"  #Xe13b)

    ;; Comparisons
    ("\\(<=\\)" #Xe141) ("\\(>=\\)" #Xe145)
    ("\\(</\\)" #Xe162) ("\\(</>\\)" #Xe163)

    ;; Shifts
    ("[^-=]\\(>>\\)" #Xe147) ("\\(>>>\\)" #Xe14a)
    ("[^-=]\\(<<\\)" #Xe15c) ("\\(<<<\\)" #Xe15f)

    ;; Dots
    ("\\(\\.-\\)"    #Xe122) ("\\(\\.=\\)" #Xe123)
    ("\\(\\.\\.<\\)" #Xe125)

    ;; Hashes
    ("\\(#{\\)"  #Xe119) ("\\(#(\\)"   #Xe11e) ("\\(#_\\)"   #Xe120)
    ("\\(#_(\\)" #Xe121) ("\\(#\\?\\)" #Xe11f) ("\\(#\\[\\)" #Xe11a)

    ;; REPEATED CHARACTERS
    ;; 2-Repeats
    ("\\(||\\)" #Xe132)
    ("\\(!!\\)" #Xe10d)
    ("\\(%%\\)" #Xe16a)
    ("\\(&&\\)" #Xe131)

    ;; 2+3-Repeats
    ("\\(##\\)"       #Xe11b) ("\\(###\\)"          #Xe11c) ("\\(####\\)" #Xe11d)
    ("\\(--\\)"       #Xe111) ("\\(---\\)"          #Xe112)
    ("\\({-\\)"       #Xe108) ("\\(-}\\)"           #Xe110)
    ("\\(\\\\\\\\\\)" #Xe106) ("\\(\\\\\\\\\\\\\\)" #Xe107)
    ("\\(\\.\\.\\)"   #Xe124) ("\\(\\.\\.\\.\\)"    #Xe126)
    ("\\(\\+\\+\\)"   #Xe138) ("\\(\\+\\+\\+\\)"    #Xe139)
    ("\\(//\\)"       #Xe12f) ("\\(///\\)"          #Xe130)
    ("\\(::\\)"       #Xe10a) ("\\(:::\\)"          #Xe10b)

    ;; ARROWS
    ;; Direct
    ("[^-]\\(->\\)" #Xe114) ("[^=]\\(=>\\)" #Xe13f)
    ("\\(<-\\)"     #Xe152)
    ("\\(-->\\)"    #Xe113) ("\\(->>\\)"    #Xe115)
    ("\\(==>\\)"    #Xe13e) ("\\(=>>\\)"    #Xe140)
    ("\\(<--\\)"    #Xe153) ("\\(<<-\\)"    #Xe15d)
    ("\\(<==\\)"    #Xe158) ("\\(<<=\\)"    #Xe15e)
    ("\\(<->\\)"    #Xe154) ("\\(<=>\\)"    #Xe159)

    ;; Branches
    ("\\(-<\\)"  #Xe116) ("\\(-<<\\)" #Xe117)
    ("\\(>-\\)"  #Xe144) ("\\(>>-\\)" #Xe148)
    ("\\(=<<\\)" #Xe142) ("\\(>>=\\)" #Xe149)
    ("\\(>=>\\)" #Xe146) ("\\(<=<\\)" #Xe15a)

    ;; Squiggly
    ("\\(<~\\)" #Xe160) ("\\(<~~\\)" #Xe161)
    ("\\(~>\\)" #Xe167) ("\\(~~>\\)" #Xe169)
    ("\\(-~\\)" #Xe118) ("\\(~-\\)"  #Xe165)

    ;; MISC
    ("\\(www\\)"                   #Xe100)
    ("\\(<!--\\)"                  #Xe151)
    ("\\([email protected]\\)"                    #Xe164)
    ("[^<]\\(~~\\)"                #Xe168)
    ("\\(\\?=\\)"                  #Xe127)
    ("[^=]\\(:=\\)"                #Xe10c)
    ("\\(/>\\)"                    #Xe12e)
    ("[^\\+<>]\\(\\+\\)[^\\+<>]"   #Xe16d)
    ("[^:=]\\(:\\)[^:=]"           #Xe16c)
    ("\\(<=\\)"                    #Xe157))
  "Fira font ligatures and their regexes.")

(if (fboundp 'mac-auto-operator-composition-mode)
    (mac-auto-operator-composition-mode)
  (pretty-fonts-set-kwds
   '((pretty-fonts-fira-font prog-mode-hook org-mode-hook))))

Prescient

(straight-use-package 'prescient)
;; (straight-use-package 'ivy-prescient)
(straight-use-package 'company-prescient)

(use-package prescient
  :hook ((after-init . prescient-persist-mode)))


(use-package ivy-prescient
  :disabled t
  :ghook 'after-init-hook)


(use-package company-prescient
  :ghook 'after-init-hook)

Projectile

(straight-use-package 'projectile)
(use-package projectile
  :defer t
  :diminish
  :bind-keymap ("C-c C-p" . projectile-command-map)
  :hook ((after-init . projectile-global-mode))
  :config (gsetq projectile-indexing-method      'hybrid
                 projectile-require-project-root 'prompt
                 projectile-project-root-files-top-down-recurring
                 (append '("compile_commands.json"
                           ".cquery")
                         projectile-project-root-files-top-down-recurring)))

Recentf

(use-package recentf
  :ghook 'after-init-hook
  :init (gsetq
         recentf-save-file       "~/.emacs.d/var/recentf"
         recentf-max-saved-items 100
         recentf-exclude         '("/tmp/" "/ssh:"))
  :config
  (add-to-list 'recentf-exclude no-littering-var-directory)
  (add-to-list 'recentf-exclude no-littering-etc-directory))

Smex/Amx

Now use amx instead of smex.

(straight-use-package 'amx)
(use-package amx
  :init (setq-default amx-save-file (no-littering-expand-var-file-name ".amx-items"))
  :bind (("<remap> <execute-extended-command>" . amx)))

Subword

(use-package subword
  :defer t
  :diminish (subword-mode))

Symbol Overlay

(straight-use-package 'symbol-overlay)
(use-package symbol-overlay
  :bind (("M-i"  . symbol-overlay-put)
         ("M-n"  . symbol-overlay-switch-forward)
         ("M-p"  . symbol-overlay-switch-backward)
         ("<f8>" . symbol-overlay-remove-all)
         ("<f7>" . symbol-overlay-mode)))

Treemacs

(straight-use-package 'treemacs)
(use-package treemacs
  :defer t
  :init
  (with-eval-after-load 'winum
    (define-key winum-keymap (kbd "M-0") #'treemacs-select-window))
  :config
  (gsetq treemacs-collapse-dirs                 (if treemacs-python-executable 3 0)
         treemacs-deferred-git-apply-delay      0.5
         treemacs-display-in-side-window        t
         treemacs-eldoc-display                 t
         treemacs-file-event-delay              5000
         treemacs-file-follow-delay             0.2
         treemacs-follow-after-init             t
         treemacs-git-command-pipe              ""
         treemacs-goto-tag-strategy             'refetch-index
         treemacs-indentation                   2
         treemacs-indentation-string            " "
         treemacs-is-never-other-window         nil
         treemacs-max-git-entries               5000
         treemacs-missing-project-action        'ask
         treemacs-no-png-images                 nil
         treemacs-no-delete-other-windows       t
         treemacs-project-follow-cleanup        nil
         treemacs-persist-file
         (no-littering-expand-var-file-name "treemacs-persist")
         treemacs-position                      'left
         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-show-cursor                   nil
         treemacs-show-hidden-files             t
         treemacs-silent-filewatch              nil
         treemacs-silent-refresh                nil
         treemacs-sorting                       'alphabetic-desc
         treemacs-space-between-root-nodes      t
         treemacs-tag-follow-cleanup            t
         treemacs-tag-follow-delay              1.5
         treemacs-width                         35)

  ;; 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 t)
  (pcase (cons (not (null (executable-find "git")))
               (not (null treemacs-python-executable)))
    (`(t . t)
     (treemacs-git-mode 'deferred))
    (`(t . _)
     (treemacs-git-mode 'simple)))
  :config
  (general-define-key
   :keymaps 'global-map
   "M-0" 'treemacs-select-window)
  (general-define-key
   :prefix "C-x t"
   :keymaps 'global-map
   "1"   'treemacs-delete-other-windows
   "t"   'treemacs
   "B"   'treemacs-bookmark
   "C-t" 'treemacs-find-file
   "M-t" 'treemacs-find-tag))


(straight-use-package 'treemacs-projectile)
(straight-use-package 'treemacs-icons-dired)
(straight-use-package 'treemacs-magit)

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

(use-package treemacs-icons-dired
  :after treemacs dired
  :config (treemacs-icons-dired-mode))

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

Undo/Redo

Point History
(straight-use-package '(point-history :type git :host github :repo "blue0513/point-history"))
(use-package point-history
  :ghook 'after-init-hook
  :bind (("C-c C-/" . point-history-show))
  :init (gsetq point-history-ignore-buffer "^ \\*Minibuf\\|^ \\*point-history-show*"))
Undo Propose
(straight-use-package 'undo-propose)
(use-package undo-propose
  :defer
  :config (undo-propose-wrap redo))

Version Control

Useful Simple Packages
(dolist (package '(git-blamed
                   git-timemachine))
  (straight-use-package package))
Git Modes
(straight-use-package 'git-modes)
Magit
(straight-use-package 'magit)
(use-package magit
  :defer t
  :commands magit-status
  :hook ((magit-popup-mode-hook . no-trailing-whitespace)
         (git-commit-mode . goto-address-mode))
  :init (gsetq magit-diff-refine-hunk t)
  :bind (([(meta f12)] . magit-status)  ;; Hint: customize `magit-repository-directories' so that you can use C-u M-F12 to
         ("C-x g"      . magit-status)
         ("C-x M-g"    . magit-dispatch-popup)
         :map magit-status-mode-map
         ("C-M-<up>"   . magit-section-up)
         :map vc-prefix-map
         ("f"          . vc-git-grep))
  :config
  (gsetq vc-handled-backends nil)
  (when *is-a-mac* (add-hook 'magit-mode-hook (lambda () (local-unset-key [(meta h)])))))

(straight-use-package 'magit-todos)
(use-package magit-todos
  :defer t
  :hook ((magit-status-mode . magit-todos-mode)))
Magit Org Todos
(straight-use-package 'magit-org-todos)
(use-package magit-org-todos
  :defer t
  :config (magit-org-todos-autoinsert))
Forge
(straight-use-package 'forge)
Transient
(straight-use-package 'transient)
(use-package transient
  :init (gsetq transient-default-level 5))
Git Messenger
(straight-use-package 'git-messenger)
(use-package git-messenger
  :init (gsetq git-messenger:show-detail t)
  :bind (:map vc-prefix-map
         ("p" . git-messenger:popup-message)))
Git Gutter
(straight-use-package 'git-gutter)
(use-package git-gutter
  :diminish
  :hook (after-init . global-git-gutter-mode)
  :init (gsetq git-gutter:visual-line t
               git-gutter:disabled-modes '(asm-mode image-mode)
               git-gutter:modified-sign "❚"
               git-gutter:added-sign "✚"
               git-gutter:deleted-sign "✘")

  :config (general-define-key
           :prefix "C-x"
           "v =" 'git-gutter:popup-hunk
           "p"   'git-gutter:previous-hunk
           "n"   'git-gutter:next-hunk))
Github Gist
(straight-use-package 'gist)

Which Function

(use-package which-func
  :defer t
  :ghook 'after-init-hook)

Which Key

(straight-use-package 'which-key)
(use-package which-key
  :ghook 'after-init-hook)

Whitespace

(use-package whitespace
  :preface
  (defun no-trailing-whitespace ()
    "Turn off display of trailing whitespace in this buffer."
    (setq show-trailing-whitespace nil))
  :init
  (gsetq-default show-trailing-whitespace t)

  ;; But don't show trailing whitespace in SQLi, inf-ruby etc.
  (dolist (hook '(artist-mode-hook
                  picture-mode-hook
                  special-mode-hook
                  Info-mode-hook
                  eww-mode-hook
                  term-mode-hook
                  vterm-mode-hook
                  comint-mode-hook
                  compilation-mode-hook
                  twittering-mode-hook
                  minibuffer-setup-hook
                  fundamental-mode))
    (add-hook hook #'no-trailing-whitespace))
  :diminish whitespace-mode)

(straight-use-package 'whitespace-cleanup-mode)
(use-package whitespace-cleanup-mode
  :init
  (gsetq whitespace-cleanup-mode-only-if-initially-clean nil)
  (gsetq-default whitespace-style
                 '(face tabs spaces trailing space-before-tab
                        newline indentation empty space-after-tab
                        space-mark tab-mark newline-mark))
  :hook ((after-init . global-whitespace-cleanup-mode))
  :diminish (whitespace-cleanup-mode)
  :bind (("<remap> <just-one-space>" . cycle-spacing)))

Writeroom Mode

(straight-use-package 'writeroom-mode)
(use-package writeroom-mode
  :defer t
  :preface
  (define-minor-mode prose-mode
    "Set up a buffer for prose editing.
This enables or modifies a number of settings so that the
experience of editing prose is a little more like that of a
typical word processor."
    nil " Prose" nil
    (if prose-mode
        (progn
          (when (fboundp 'writeroom-mode)
            (writeroom-mode 1))
          (setq truncate-lines nil)
          (setq word-wrap t)
          (setq cursor-type 'bar)
          (when (eq major-mode 'org)
            (kill-local-variable 'buffer-face-mode-face))
          (buffer-face-mode 1)
          ;;(delete-selection-mode 1)
          (set (make-local-variable 'blink-cursor-interval) 0.6)
          (set (make-local-variable 'show-trailing-whitespace) nil)
          (set (make-local-variable 'line-spacing) 0.2)
          (set (make-local-variable 'electric-pair-mode) nil)
          (ignore-errors (flyspell-mode 1))
          (visual-line-mode 1))
      (kill-local-variable 'truncate-lines)
      (kill-local-variable 'word-wrap)
      (kill-local-variable 'cursor-type)
      (kill-local-variable 'show-trailing-whitespace)
      (kill-local-variable 'line-spacing)
      (kill-local-variable 'electric-pair-mode)
      (buffer-face-mode -1)
      ;; (delete-selection-mode -1)
      (flyspell-mode -1)
      (visual-line-mode -1)
      (when (fboundp 'writeroom-mode)
        (writeroom-mode 0)))))

Yasnipeet

(straight-use-package 'yasnippet)
(straight-use-package 'yasnippet-snippets)

(use-package yasnippet
  :defer t
  :bind (:map yas-minor-mode-map
              ("C-'" . yas-expand))
  :commands (yas-minor-mode)
  :hook ((prog-mode . yas-minor-mode))
  :config (yas-reload-all)
  :diminish yas-minor-mode)

Languages

English

Dict
(straight-use-package 'bing-dict)
(use-package bing-dict
  :bind (("C-c d" . bing-dict-brief))
  :init (gsetq bing-dict-show-thesaurus  'both
               bing-dict-vocabulary-save t
               bing-dict-cache-auto-save t
               bing-dict-vocabulary-file
               (no-littering-expand-var-file-name "bing-dict/vocabulary.org")
               bing-dict-cache-file
               (no-littering-expand-var-file-name "bing-dict/bing-dict-save.el")))
Spell
(use-package ispell
  :if *ispell*
  :init
  (gsetq-default ispell-program-name   *ispell*
                 ispell-silently-savep t
                 ispell-dictionary     "english"
                 ispell-personal-dictionary
                 (no-littering-expand-var-file-name "ispell/dictionary"))
  (when (string-suffix-p "aspell" *ispell*)
    (gsetq-default ispell-extra-args '("--reverse"))))

(unless *ispell*
  (message "if you want to use ispell, try\n brew install aspell\n brew install ispell"))

Simple Supported Languages

(let ((languages '(elvish-mode
                   fish-mode
                   toml-mode
                   yaml-mode))
      (extras    '(fish-completion
                   ob-elvish)))
  (dolist (language languages)
    (straight-use-package language))
  (dolist (extra extras)
    (straight-use-package extra)))

Language Server Protocol & Debug Adapter Protocol

lsp-mode
(straight-use-package 'lsp-mode)
(use-package lsp-mode
  :commands (lsp lsp-deferred)
  :preface
  (defun delete-company-lsp ()
    "Delete company-lsp added by lsp-mode from company-backends"
    (when 'company-backends
      (gsetq company-backends (delete 'company-lsp company-backends)
             company-backends (delete 'intero-company company-backends))))
  :hook ((lsp-after-open . lsp-enable-imenu)
         ((lsp-mode
           lsp-after-open
           prog-mode
           company-box-mode
           company-mode) . delete-company-lsp))
  :init (gsetq lsp-print-io                     t
               lsp-print-performance            t
               lsp-inhibit-message              t
               lsp-report-if-no-buffer          t
               lsp-keep-workspace-alive         nil
               lsp-enable-snippet               t
               lsp-restart                      'auto-restart
               lsp-document-sync-method         'full
               lsp-eldoc-render-all             t
               lsp-enable-completion-at-point   t
               lsp-enable-xref                  t
               lsp-enable-indentation           t
               lsp-prefer-flymake               nil
               lsp-enable-on-type-formatting    t
               lsp-enable-semantic-highlighting t))
lsp-ui
(straight-use-package 'lsp-ui)
(use-package lsp-ui
  :commands lsp-ui-mode
  :bind (:map lsp-ui-mode-map
              ("M-,"  . lsp-ui-peek-find-definitions)
              ("M-?"  . lsp-ui-peek-find-references)
              ("C-c u"   . lsp-ui-imenu)
              ("C-c C-a" . lsp-ui-sideline-apply-code-actions))
  :ghook 'lsp-mode-hook
  :init
  (gsetq lsp-ui-doc-position 'at-point
         lsp-ui-doc-header nil
         lsp-ui-doc-border "violet"
         ;; lsp-ui-doc-include-signature t
         lsp-ui-sideline-update-mode 'point
         lsp-ui-sideline-delay 1
         lsp-ui-sideline-ignore-duplicate t
         lsp-ui-peek-always-show t
         lsp-ui-flycheck-enable t))
company-lsp
(straight-use-package 'company-lsp)
(use-package company-lsp
  :after company
  :defer t
  :commands company-lsp
  :init
  (with-eval-after-load 'company-mode
    (general-pushnew
     '(company-lsp
       company-files
       company-dabbrev-code
       company-gtags
       company-etags
       company-keywords
       :with company-yasnippet)
     company-backends))
  (gsetq company-lsp-async               t
         company-lsp-enable-recompletion t
         company-transformers            nil
         company-lsp-enable-snippet      t
         company-lsp-cache-candidates    nil)
  :config
  (setcdr (assq 'pyls company-lsp-filter-candidates) t))
Dap Mode
(straight-use-package 'dap-mode)
Helm Lsp
(straight-use-package 'helm-lsp)
(use-package helm-lsp :commands helm-lsp-workspace-symbol)
lsp-treemacs
(straight-use-package 'lsp-treemacs)
(use-package lsp-treemacs
  :commands lsp-treemacs-errors-list
  :config
  (lsp-metals-treeview-enable t)
  (gsetq lsp-metals-treeview-show-when-views-received t))

C/C++/Object-C (Clangd or ccls)

Clangd or ccls.

clangd
(use-package lsp-mode
  :if *clangd*
  :hook (((c-mode c++-mode objc-mode) . lsp-deferred))
  :init (setq-default lsp-clients-clangd-executable *clangd*))
ccls
(when *ccls*
  (straight-use-package 'ccls)
  (use-package ccls
    :preface
    (defun ccls/load ()
      (require 'ccls)
      (lsp-deferred))
    :hook (((c-mode c++-mode objc-mode) . ccls/load))
    :init (gsetq ccls-executable *ccls*
                 ccls-initialization-options
                 '(:clang (:extraArgs
                           ["-isysroot"
                            "/Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX.sdk"]))
                 ccls-sem-highlight-method 'font-lock)
    :config
    (ccls-use-default-rainbow-sem-highlight)
    (defun ccls/callee ()
      (interactive)
      (lsp-ui-peek-find-custom "$ccls/call" '(:callee t)))
    (defun ccls/caller ()
      (interactive)
      (lsp-ui-peek-find-custom "$ccls/call"))
    (defun ccls/vars (kind)
      (lsp-ui-peek-find-custom "$ccls/vars" `(:kind ,kind)))
    (defun ccls/base (levels)
      (lsp-ui-peek-find-custom "$ccls/inheritance" `(:levels ,levels)))
    (defun ccls/derived (levels)
      (lsp-ui-peek-find-custom "$ccls/inheritance" `(:levels ,levels :derived t)))
    (defun ccls/member (kind)
      (lsp-ui-peek-find-custom "$ccls/member" `(:kind ,kind)))

    ;; The meaning of :role corresponds to https://github.com/maskray/ccls/blob/master/src/symbol.h

    ;; References w/ Role::Address bit (e.g. variables explicitly being taken addresses)
    (defun ccls/references-address ()
      (interactive)
      (lsp-ui-peek-find-custom "textDocument/references"
       (plist-put (lsp--text-document-position-params) :role 128)))

    ;; References w/ Role::Dynamic bit (macro expansions)
    (defun ccls/references-macro ()
      (interactive)
      (lsp-ui-peek-find-custom "textDocument/references"
       (plist-put (lsp--text-document-position-params) :role 64)))

    ;; References w/o Role::Call bit (e.g. where functions are taken addresses)
    (defun ccls/references-not-call ()
      (interactive)
      (lsp-ui-peek-find-custom "textDocument/references"
       (plist-put (lsp--text-document-position-params) :excludeRole 32)))

    ;; References w/ Role::Read
    (defun ccls/references-read ()
      (interactive)
      (lsp-ui-peek-find-custom "textDocument/references"
       (plist-put (lsp--text-document-position-params) :role 8)))

    ;; References w/ Role::Write
    (defun ccls/references-write ()
      (interactive)
      (lsp-ui-peek-find-custom "textDocument/references"
       (plist-put (lsp--text-document-position-params) :role 16)))

    ;; xref-find-apropos (workspace/symbol)

    (defun my/highlight-pattern-in-text (pattern line)
      (when (> (length pattern) 0)
        (let ((i 0))
         (while (string-match pattern line i)
           (setq i (match-end 0))
           (add-face-text-property (match-beginning 0) (match-end 0) 'isearch t line))

         line)))

    (with-eval-after-load 'lsp-methods
      ;;; Override
      ;; This deviated from the original in that it highlights pattern appeared in symbol
      (defun lsp--symbol-information-to-xref (pattern symbol)
       "Return a `xref-item' from SYMBOL information."
       (let* ((location (gethash "location" symbol))
              (uri (gethash "uri" location))
              (range (gethash "range" location))
              (start (gethash "start" range))
              (name (gethash "name" symbol)))
         (xref-make (format "[%s] %s"
                            (alist-get (gethash "kind" symbol) lsp--symbol-kind)
                            (my/highlight-pattern-in-text (regexp-quote pattern) name))
                    (xref-make-file-location (string-remove-prefix "file://" uri)
                                             (1+ (gethash "line" start))
                                             (gethash "character" start)))))

      (cl-defmethod xref-backend-apropos ((_backend (eql xref-lsp)) pattern)
        (let ((symbols (lsp--send-request (lsp--make-request
                                           "workspace/symbol"
                                           `(:query ,pattern)))))
          (mapcar (lambda (x) (lsp--symbol-information-to-xref pattern x)) symbols))))))

Haskell

Include haskell-mode, lsp-haskell, intero and structured haskell mode. Also inlcude haskell-snippets.

Haskell-Mode
(straight-use-package 'haskell-mode)
(use-package haskell-mode
  :preface
  (define-minor-mode stack-exec-path-mode
    "If this is a stack project, set `exec-path' to the path \"stack exec\" would use."
    nil
    :lighter ""
    :global nil
    (if stack-exec-path-mode
        (when (and (executable-find "stack")
                   (locate-dominating-file default-directory "stack.yaml"))
          (setq-local
           exec-path
           (seq-uniq
            (append (list (concat (string-trim-right (shell-command-to-string "stack path --local-install-root")) "/bin"))
                    (parse-colon-path
                     (replace-regexp-in-string "[\r\n]+\\'" ""
                                               (shell-command-to-string "stack path --bin-path"))))
            'string-equal)))
      (kill-local-variable 'exec-path)))

  :gfhook '(subword-mode
            haskell-auto-insert-module-template
            haskell-collapse-mode
            stack-exec-path-mode
            interactive-haskell-mode
            (lambda () (gsetq-local tab-width 4)))
  :bind (("C-x a a" . align)
         :map haskell-mode-map
         ("C-c h" . hoogle)
         ("C-o"   . open-line))
  :init
  (gsetq haskell-mode-stylish-haskell-path            "stylish-haskell"
         haskell-indentation-layout-offset            4
         haskell-indentation-left-offset              4
         haskell-process-suggest-haskell-docs-imports t
         haskell-process-suggest-remove-import-lines  t
         haskell-process-auto-import-loaded-modules   t
         haskell-process-log                          t
         haskell-process-suggest-hayoo-imports        t
         haskell-process-suggest-hoogle-imports       t
         haskell-process-suggest-remove-import-lines  t
         haskell-tags-on-save                         t
         haskell-completing-read-function             'helm--completing-read-default
         haskell-doc-show-global-types                t
         haskell-svg-render-images                    t
         haskell-doc-chop-off-context                 nil)

  (unless *struct-hs*
    (add-hook #'haskell-mode-hook #'haskell-indentation-mode))

  (unless (fboundp 'align-rules-list)
    (defvar align-rules-list nil))

  (add-to-list 'align-rules-list
               '(haskell-types
                 (regexp . "\\(\\s-+\\)\\(::\\|\\)\\s-+")
                 (modes quote (haskell-mode literate-haskell-mode))))
  (add-to-list 'align-rules-list
               '(haskell-assignment
                 (regexp . "\\(\\s-+\\)=\\s-+")
                 (modes quote (haskell-mode literate-haskell-mode))))
  (add-to-list 'align-rules-list
               '(haskell-arrows
                 (regexp . "\\(\\s-+\\)\\(->\\|\\)\\s-+")
                 (modes quote (haskell-mode literate-haskell-mode))))
  (add-to-list 'align-rules-list
               '(haskell-left-arrows
                 (regexp . "\\(\\s-+\\)\\(<-\\|\\)\\s-+")
                 (modes quote (haskell-mode literate-haskell-mode))))

  :config
  (push 'haskell-mode page-break-lines-modes)
  (defun haskell-mode-generate-tags (&optional and-then-find-this-tag)
    "Generate tags using Hasktags.  This is synchronous function.

  If optional AND-THEN-FIND-THIS-TAG argument is present it is used
  with function `xref-find-definitions' after new table was
  generated."
    (interactive)
    (let* ((dir (haskell-cabal--find-tags-dir))
           (command (haskell-cabal--compose-hasktags-command dir)))
      (if (not command)
          (error "Unable to compose hasktags command")
        ;; I disabled the noisy shell command output.
        ;; The original is (shell-command command)
        (call-process-shell-command command nil "*Shell Command Output*" t)
        (haskell-mode-message-line "Tags generated.")
        (when and-then-find-this-tag
          (let ((tags-file-name dir))
            (xref-find-definitions and-then-find-this-tag)))))))
LSP Haskell
(straight-use-package 'lsp-haskell)
(use-package lsp-haskell
  :preface
  (defun start-lsp-haskell ()
    (require 'lsp-haskell)
    (lsp-deferred))
  :hook ((haskell-mode   . start-lsp-haskell)
         (lsp-after-open . (lambda () (add-hook 'before-save-hook #'lsp-format-buffer nil t)))
         (haskell-mode   . delete-company-lsp))
  :init
  (gsetq lsp-haskell-process-path-hie "hie-wrapper")
  ;; You can set the lsp-haskell settings here
  ;; (lsp-haskell-set-hlint-on)                    ;; default on
  ;; (lsp-haskell-set-max-number-of-problems 100)  ;; default 100
  ;; (lsp-haskell-set-liquid-on)                   ;; default off
  ;; (lsp-haskell-set-completion-snippets-on)      ;; default on
  )
intero
(when *intero*
  (straight-use-package 'intero)
  (use-package intero
    :hook ((haskell-mode . intero-mode))
    :config
    (define-key intero-mode-map (kbd "M-?") nil)
    (define-key intero-mode-map (kbd "C-c C-r") nil)))
Structured Haskell Mode
(if *struct-hs*
    (progn
      (add-to-list 'load-path *struct-hs-path*)
      (require 'shm)
      (setq shm-program-name *struct-hs*)
      (add-hook #'haskell-mode-hook #'structured-haskell-mode))
  (progn
    (when *struct-hs*
      (message (concat "*NOTE* about structured-haskell-mode:\n"
                       "https://github.com/projectional-haskell/structured-haskell-mode\n"
                       "No structured-haskell-mode elisp find.\n"
                       "If you want to use it, \n"
                       "please install it and config its variables *struct-hs-path* in user-config.el\n")))))
haskell snippets
(straight-use-package 'haskell-snippets)

HTML

(use-package lsp-html
  :hook ((html-mode . lsp-deferred)))

JavaScript & TypeScript

(use-package lsp-mode
  :disabled t
  :hook ((javascript-mode . lsp-deferred)))

Lisp

lisp-mode
(use-package lisp-mode
  :preface
  (defun eval-last-sexp-or-region (prefix)
    "Eval region from BEG to END if active, otherwise the last sexp."
    (interactive "P")
    (if (and (mark) (use-region-p))
        (eval-region (min (point) (mark)) (max (point) (mark)))
      (pp-eval-last-sexp prefix)))
  :bind (:map emacs-lisp-mode-map
         ("<remap> <eval-expression>" . pp-eval-expression)
         ("C-x C-e" . eval-last-sexp-or-region)))
Highlight-quoted
(straight-use-package 'highlight-quoted)
(use-package highlight-quoted
  :defer t
  :hook ((emacs-lisp-mode . highlight-quoted-mode)))
elisp-def
(straight-use-package 'elisp-def)
(use-package elisp-def
  :defer t
  :hook (((emacs-lisp-mode ielm-mode) . elisp-def-mode)))

Markdown

(straight-use-package 'markdown-mode)
(use-package markdown-mode
  :defer t
  :mode ("INSTALL\\'"
         "CONTRIBUTORS\\'"
         "LICENSE\\'"
         "README\\'"
         "\\.markdown\\'"
         "\\.md\\'"))

Pandoc

(straight-use-package 'pandoc-mode)

Python

Include python-mode, black, py-isort, python-docstring and sphinx-doc.

Python Mode
(straight-use-package 'python-mode)
(use-package python-mode
  :commands python-mode
  :mode ("\\.py\\'" . python-mode)
  :interpreter (("python"  . python-mode)
                ("python3" . python-mode))
  :preface
  ;; TODO: Need improve.
  (defun setq-after ()
    "setq after python mode."
    (when (projectile-file-exists-p "mypy.ini")
      (gsetq flycheck-python-mypy-ini "mypy.ini"
             flycheck-mypy.ini        "mypy.ini"))

    (when (projectile-file-exists-p "pylintrc")
      (gsetq flycheck-pylintrc "pylintrc")))

  (defcustom nasy*python-buffer "vterm"
    "Nasy Python Buffer"
    :group 'python-mode
    :type 'string)

  (defun nasy/python-send-buffer ()
    "Send current buffer to the running python process."
    (interactive)
    (let ((proc (get-buffer-process nasy*python-buffer)))
      (unless proc
        (error "No process found"))
      (save-buffer)
      (comint-simple-send proc
                          (concat "%run " (format "%s" (buffer-file-name))))
      (pop-to-buffer nasy*python-buffer)))

  (defun nasy/python-send-region (begin end)
    "Evaluate the code in region from BEGIN to END in the python repl.
if the region is unset, the current line will be used."
    (interactive "r")
    (unless (use-region-p)
      (setq begin (line-beginning-position)
            end (line-end-position)))
    (let* ((text (buffer-substring-no-properties begin end))
           (proc (get-buffer-process nasy*python-buffer)))
      (unless proc
        (error "No process found"))
      (comint-simple-send proc text)
      (display-buffer nasy*python-buffer)))

  (defun nasy/python-send-defun (&optional arg)
    "Send the current defun to inferior Python process.
When ARG is non-nil do not include decorators."
    (interactive (list current-prefix-arg t))
    (nasy:python-send-region
     (progn
       (end-of-line 1)
       (while (and (or (python-nav-beginning-of-defun)
                    (beginning-of-line 1))
                 (> (current-indentation) 0)))
       (when (not arg)
         (while (and (forward-line -1)
                   (looking-at (python-rx decorator))))
         (forward-line 1))
       (point-marker)
       (progn
         (or (python-nav-end-of-defun)
            (end-of-line 1))
         (point-marker)))))

  (defun nasy/python-switch-to-shell ()
    "Switch to inferior Python process buffer."
    (interactive "p")
    (let ((proc (get-buffer-process nasy:python-buffer)))
      (unless proc
        (error "No process found"))
      (pop-to-buffer nasy*python-buffer)))
  :gfhook '(lsp-deferred
            delete-company-lsp
            setq-after)
  :init
  (general-define-key
   :prefix "C-c"
   :keymaps 'python-mode-map
   "C-b" 'nasy/python-send-buffer
   "C-r" 'nasy/python-send-region
   "C-c" 'nasy/python-send-defun
   "C-z" 'nasy/python-switch-to-shell)
  (general-define-key
   :keymaps 'python-mode-map
   "<S-return>" 'nasy/python-send-region)
  (gsetq python-indent-offset                  4
         indent-tabs-mode                      nil
         python-indent-guess-indent-offset     nil
         python-shell-completion-native-enable nil
         python-shell-interpreter              "ipython3"
         python-shell-interpreter-args         "-i"
         py-ipython-command-args               "-i"
         py-python-command                     "python3"
         flycheck-python-pycompile-executable  "python3"
         flycheck-python-pylint-executable     "python3"
         python-mode-modeline-display          "Python"
         python-skeleton-autoinsert            t
         py-python-command                     "python3"
         py-python2-command                    "python2"
         py-python3-command                    "python3"
         py-ipython-command                    "ptipython"
         py-ipython2-command                   "ipython2"
         py-ipython3-command                   "ipython3"
         py-set-fill-column-p                  t
         py-shell-name                         nasy*python-buffer)

  ;; A list here https://github.com/palantir/python-language-server/blob/develop/vscode-client/package.json#L23-L230
  ;; I prefer pydocstyle and black, so disabled yapf, though, pydocstyle still cannot be abled.
  ;; pip install black pyls-black -U
  ;; The default line-length is 88 when using black, you can add a file named "pyproject.yaml" that contains
  ;; [tool.black]
  ;; line-length = 79
  (with-eval-after-load 'lsp-pyls
    (gsetq lsp-pyls-configuration-sources                          ["pydocstyle" "pycodestyle" "pyflakes" "pylint"]
           lsp-pyls-plugins-pydocstyle-enabled                     t
           lsp-pyls-plugins-yapf-enabled                           t
           lsp-pyls-plugins-jedi-definition-follow-imports         t
           lsp-pyls-plugins-jedi-definition-follow-builtin-imports t
           lsp-pyls-plugins-jedi-signature-help-enabled            t
           lsp-pyls-plugins-jedi-symbols-enabled                   t
           lsp-pyls-plugins-pyls_mypy-live-mode                    nil))
  :config
  (unless *blacken*
    (add-hook #'python-mode-hook
              #'(lambda () (add-hook #'before-save-hook #'lsp-format-buffer nil t)))))
black
;; Now you can use it in lsp.
;; NOTICE you have to config black though pyproject.toml.
(when *blacken*
  (straight-use-package 'blacken)
  (use-package blacken
    :hook ((python-mode . blacken-mode))))
py-isort
(straight-use-package 'py-isort)
(use-package py-isort
  :hook ((before-save . py-isort-before-save)))
Python Docstring
(straight-use-package 'python-docstring)
(use-package python-docstring
  :hook ((python-mode . python-docstring-mode)))
Sphinx Doc
(straight-use-package 'sphinx-doc)
(use-package sphinx-doc
  :hook ((python-mode . sphinx-doc-mode)))
pyimport
(straight-use-package 'pyimport)
(use-package pyimport
  :bind (:map python-mode-map
              ("C-c C-i" . pyimport-insert-missing)))

Rust

Include rust-mode, rls and Cargo.

(when *rust*
  (straight-use-package 'rust-mode)
  (straight-use-package 'cargo)
  (use-package rust-mode
    :defer t
    :hook ((rust-mode . (lambda () (setq-local tab-width 4)))
           (rust-mode . lsp-deferred))
    :config
    (when *rls*
      (add-hook #'rust-mode-hook #'(lambda () (add-to-list 'flycheck-disabled-checkers 'rust-cargo)))))

  (use-package cargo
    :after rust-mode
    :hook ((toml-mode . cargo-minor-mode)
           (rust-mode . cargo-minor-mode))))

Org Mode

Load

I use org with org-plus-contrib

(straight-use-package 'org-plus-contrib)

Basic Configs

(use-package org
  :preface
  (advice-add 'org-refile :after (lambda (&rest _) (org-save-all-org-buffers)))

  ;; Exclude DONE state tasks from refile targets
  (defun verify-refile-target ()
    "Exclude todo keywords with a done state from refile targets."
    (not (member (nth 2 (org-heading-components)) org-done-keywords)))
  (setq org-refile-target-verify-function 'verify-refile-target)

  (defun org-refile-anywhere (&optional goto default-buffer rfloc msg)
    "A version of `org-refile' which allows refiling to any subtree."
    (interactive "P")
    (let ((org-refile-target-verify-function))
      (org-refile goto default-buffer rfloc msg)))

  (defun org-agenda-refile-anywhere (&optional goto rfloc no-update)
    "A version of `org-agenda-refile' which allows refiling to any subtree."
    (interactive "P")
    (let ((org-refile-target-verify-function))
      (org-agenda-refile goto rfloc no-update)))

  ;; The original from spacemacs chinese layer shows as follow.
  ;;   (defadvice org-html-paragraph (before org-html-paragraph-advice
  ;;                                         (paragraph contents info) activate)
  ;;     "Join consecutive Chinese lines into a single long line without
  ;; unwanted space when exporting org-mode to html."
  ;;     (let* ((origin-contents (ad-get-arg 1))
  ;;            (fix-regexp "[[:multibyte:]]")
  ;;            (fixed-contents
  ;;             (replace-regexp-in-string
  ;;              (concat
  ;;               "\\(" fix-regexp "\\) *\n *\\(" fix-regexp "\\)") "\\1\\2" origin-contents)))
  ;;       (ad-set-arg 1 fixed-contents)))

  (defun nasy/org-html-paragraph-advice (orig paragraph contents &rest args)
    "Join consecutive Chinese lines into a single long line without
unwanted space when exporting org-mode to html."
    (let* ((fix-regexp "[[:multibyte:]]")
           (fixed-contents
            (replace-regexp-in-string
             (concat
              "\\(" fix-regexp "\\) *\n *\\(" fix-regexp "\\)") "\\1\\2" contents)))
      (apply orig paragraph fixed-contents args)))
  (advice-add #'org-html-paragraph :around #'nasy/org-html-paragraph-advice)

  (defun nasy/org-fix-saveplace ()
    "Fix a problem with saveplace.el putting you back in a folded position"
    (when (outline-invisible-p)
      (save-excursion
        (outline-previous-visible-heading 1)
        (org-show-subtree))))

  (defvar-local nasy/org-at-src-begin -1
    "Variable that holds whether last position was a ")

  (defvar nasy/ob-header-symbol ?☰
    "Symbol used for babel headers")

  (defun nasy/org-prettify-src--update ()
    (let ((case-fold-search t)
          (re "^[ \t]*#\\+begin_src[ \t]+[^ \f\t\n\r\v]+[ \t]*")
          found)
      (save-excursion
        (goto-char (point-min))
        (while (re-search-forward re nil t)
          (goto-char (match-end 0))
          (let ((args (org-trim
                       (buffer-substring-no-properties (point)
                                                       (line-end-position)))))
            (when (org-string-nw-p args)
              (let ((new-cell (cons args nasy/ob-header-symbol)))
                (cl-pushnew new-cell prettify-symbols-alist :test #'equal)
                (cl-pushnew new-cell found :test #'equal)))))
        (setq prettify-symbols-alist
              (cl-set-difference prettify-symbols-alist
                                 (cl-set-difference
                                  (cl-remove-if-not
                                   (lambda (elm)
                                     (eq (cdr elm) nasy/ob-header-symbol))
                                   prettify-symbols-alist)
                                  found :test #'equal)))
        ;; Clean up old font-lock-keywords.
        (font-lock-remove-keywords nil prettify-symbols--keywords)
        (setq prettify-symbols--keywords (prettify-symbols--make-keywords))
        (font-lock-add-keywords nil prettify-symbols--keywords)
        (while (re-search-forward re nil t)
          (font-lock-flush (line-beginning-position) (line-end-position))))))

  (defun nasy/org-prettify-src ()
    "Hide src options via `prettify-symbols-mode'.

  `prettify-symbols-mode' is used because it has uncollpasing. It's
  may not be efficient."
    (let* ((case-fold-search t)
           (at-src-block (save-excursion
                           (beginning-of-line)
                           (looking-at "^[ \t]*#\\+begin_src[ \t]+[^ \f\t\n\r\v]+[ \t]*"))))
      ;; Test if we moved out of a block.
      (when (or (and nasy/org-at-src-begin
                     (not at-src-block))
                ;; File was just opened.
                (eq nasy/org-at-src-begin -1))
        (nasy/org-prettify-src--update))
      ;; Remove composition if at line; doesn't work properly.
      ;; (when at-src-block
      ;;   (with-silent-modifications
      ;;     (remove-text-properties (match-end 0)
      ;;                             (1+ (line-end-position))
      ;;                             '(composition))))
      (setq nasy/org-at-src-begin at-src-block)))

  (defun nasy/org-prettify-symbols ()
    (mapc (apply-partially 'add-to-list 'prettify-symbols-alist)
          (cl-reduce 'append
                     (mapcar (lambda (x) (list x (cons (upcase (car x)) (cdr x))))
                             `(("#+begin_src" . ?λ)
                               ("#+end_src"   . ?⌞)
                               ("#+header:" . ,nasy/ob-header-symbol)
                               ("#+begin_quote" . ?✎)
                               ("#+end_quote" . ?⌞)))))
    (turn-on-prettify-symbols-mode)
    (add-hook 'post-command-hook 'nasy/org-prettify-src t t))

  :bind (("C-c l" . org-store-link)
         ("C-c a" . org-agenda)
         ("C-c c" . org-capture)
         :map org-mode-map
         ("C-M-<up>" . org-up-element)
         ("M-h"      . nil)
         ("C-c g"    . org-mac-grab-link)
         ("C-c _"    . org-edit-special)
         :map org-src-mode-map
         ("C-c _"    . org-edit-src-exit))
  :hook ((org-mode . auto-fill-mode)
         (org-mode . nasy/org-fix-saveplace)
         (org-mode . nasy/org-prettify-symbols))
  :init
  (gsetq
   org-archive-mark-done nil
   org-archive-location  "%s_archive::* Archive"
   org-archive-mark-done nil

   org-catch-invisible-edits 'smart

   org-default-notes-file "~/notes/default.org"

   org-edit-timestamp-down-means-later t

   org-ellipsis " ﹅"

   org-emphasis-regexp-components ;; markup chinesee without space
      (list (concat " \t('\"{"            "[:nonascii:]")
            (concat "- \t.,:!?;'\")}\\["  "[:nonascii:]")
            " \t\r\n,\"'"
            "."
            1)

   org-export-backends                           '(ascii html latex md)
   org-export-coding-system                      'utf-8
   org-export-kill-product-buffer-when-displayed t
   org-export-with-broken-links                  'mark
   org-export-with-sub-superscripts              '{}
   org-use-sub-superscripts                      '{}

   org-fast-tag-selection-single-key 'expert

   org-highlight-latex-and-related: '(native latex script entities)

   org-hide-emphasis-markers t
   org-hide-leading-stars    nil

   org-html-checkbox-type       'uncode
   org-html-doctype             "html5"
   org-html-html5-fancy         t
   org-html-htmlize-output-type 'inline-css
   org-html-klipsify-src        t
   org-html-mathjax-options     '((path          "https://cdnjs.cloudflare.com/ajax/libs/mathjax/2.7.5/latest.js?config=TeX-AMS-MML_HTMLorMML")
                                  (scale         "100")
                                  (align         "center")
                                  (font          "Neo-Euler")
                                  (linebreaks    "false")
                                  (autonumber    "AMS")
                                  (indent        "0em")
                                  (multlinewidth "85%")
                                  (tagindent     ".8em")
                                  (tagside       "right"))
   org-html-with-latex          'mathjax
   org-html-validation-link     nil

   org-indent-mode-turns-on-hiding-stars nil

   org-pretty-entities t

   ;; org time
   ;; org-display-custom-times         t  ;; should setq-default
   org-time-stamp-custom-formats    '("<%a %b %d, %Y>" . "<%a %b %d %H:%M:%S %Y>")
   org-export-date-timestamp-format "%b %d, %Y"

   ;; org latex
   org-latex-compiler "lualatex"
   org-latex-default-packages-alist
   (quote
    (("AUTO" "inputenc"  t   ("pdflatex"))
     ("T1"   "fontenc"   t   ("pdflatex"))
     (""     "graphicx"  t   nil)
     (""     "grffile"   t   nil)
     (""     "longtable" t   nil)
     (""     "booktabs"  t   nil)
     (""     "wrapfig"   nil nil)
     (""     "rotating"  nil nil)
     ("normalem" "ulem"  t   nil)
     (""     "amsmath"   t   nil)
     (""     "textcomp"  t   nil)
     (""     "amssymb"   t   nil)
     (""     "capt-of"   nil nil)
     ("colorlinks,unicode,linkcolor=blue,anchorcolor=blue,citecolor=green,filecolor=black,urlcolor=blue"
      "hyperref" t nil)
     (""            "luatexja-fontspec" t nil)
     (""            "listings"          t nil)
     ("cache=false" "minted"            t nil)))
   org-latex-default-table-environment "longtable"
   org-latex-listings 'minted
   org-latex-listings-langs
   (quote
    ((emacs-lisp   "Lisp")
     (lisp         "Lisp")
     (clojure      "Lisp")
     (c            "C")
     (C            "C")
     (cc           "C++")
     (fortran      "fortran")
     (perl         "Perl")
     (cperl        "Perl")
     (Python       "Python")
     (python       "Python")
     (ruby         "Ruby")
     (html         "HTML")
     (xml          "XML")
     (tex          "TeX")
     (latex        "[LaTeX]TeX")
     (sh           "bash")
     (shell-script "bash")
     (gnuplot      "Gnuplot")
     (ocaml        "Caml")
     (caml         "Caml")
     (sql          "SQL")
     (sqlite       "sql")
     (makefile     "make")
     (make         "make")
     (R            "r")))
   org-latex-pdf-process
   (quote
    ("lualatex -shell-escape -interaction nonstopmode %f"
     "lualatex -shell-escape -interaction nonstopmode %f"))
   org-latex-tables-booktabs t

   org-level-color-stars-only nil
   org-list-indent-offset 2
   org-log-done t

   org-outline-path-complete-in-steps nil

   org-refile-allow-creating-parent-nodes 'confirm
   org-refile-targets                     '((nil :maxlevel . 5) (org-agenda-files :maxlevel . 5))
   org-refile-use-cache                   nil
   org-refile-use-outline-path            t

   org-startup-indented  t
   org-startup-folded    'content
   org-startup-truncated nil

   org-src-lang-modes '(("C"         . c)
                        ("C++"       . c++)
                        ("asymptote" . asy)
                        ("bash"      . sh)
                        ("beamer"    . latex)
                        ("calc"      . fundamental)
                        ("makefile"  . fundamental)
                        ("make"      . fundamental)
                        ("cpp"       . c++)
                        ("ditaa"     . artist)
                        ("dot"       . fundamental)
                        ("elisp"     . emacs-lisp)
                        ("ocaml"     . tuareg)
                        ("screen"    . shell-script)
                        ("shell"     . sh)
                        ("sqlite"    . sql))

   org-support-shift-select t

   org-tags-column 80

   ;; to-do settings
   org-todo-keywords        (quote ((sequence "TODO(t)" "NEXT(n)" "|" "DONE(d!/!)")
                                    (sequence "PROJECT(p)" "|" "DONE(d!/!)" "CANCELLED([email protected]/!)")
                                    (sequence "WAITING([email protected]/!)" "DELEGATED(e!)" "HOLD(h)" "|" "CANCELLED([email protected]/!)")))
   org-todo-repeat-to-state "NEXT"
   org-todo-keyword-faces   (quote (("NEXT" :inherit warning)
                                    ("PROJECT" :inherit font-lock-string-face))))
  (gsetq org-display-custom-times t)
  :config
  ;; --------
  (org-babel-do-load-languages
   'org-babel-load-languages
   `((ditaa      . t)
     (dot        . t)
     (elvish     . t)
     (emacs-lisp . t)
     (gnuplot    . t)
     (haskell    . nil)
     (latex      . t)
     (ledger     . t)
     (ocaml      . nil)
     (octave     . t)
     (plantuml   . t)
     (python     . t)
     (R          . t)
     (ruby       . t)
     (screen     . nil)
     (,(if (locate-library "ob-sh") 'sh 'shell) . t)
     (sql . nil)
     (sqlite . t)))

  (gsetq org-babel-python-command "python3")

  ;; --------
  (gsetq luamagick
         '(luamagick
           :programs ("lualatex" "convert")
           :description "pdf > png"
           :message "you need to install lualatex and imagemagick."
           :use-xcolor t
           :image-input-type "pdf"
           :image-output-type "png"
           :image-size-adjust (1.0 . 1.0)
           :latex-compiler ("lualatex -interaction nonstopmode -output-directory %o %f")
           :image-converter ("convert -density %D -trim -antialias %f -quality 100 %O")))
  (add-to-list 'org-preview-latex-process-alist luamagick)

  (gsetq luasvg
         '(luasvg
           :programs ("lualatex" "dvisvgm")
           :description "dvi > svg"
           :message "you need to install lualatex and dvisvgm."
           :use-xcolor t
           :image-input-type "dvi"
           :image-output-type "svg"
           :image-size-adjust (1.7 . 1.5)
           :latex-compiler ("lualatex -interaction nonstopmode -output-format dvi -output-directory %o %f")
           :image-converter ("dvisvgm %f -n -b min -c %S -o %O")))
  (add-to-list 'org-preview-latex-process-alist luasvg)
  (gsetq org-preview-latex-default-process 'luasvg)

  (require 'org-tempo nil t)
  (with-eval-after-load 'ox
    (let ((oxs '(ox-rst
                 ox-pandoc)))
      (dolist (language oxs)
        (straight-use-package language)
        (require language nil t)))))

Org Agenda

(use-package org-agenda
  :init (gsetq-default org-agenda-clockreport-parameter-plist '(:link t :maxlevel 3))
  :hook ((org-agenda-mode . (lambda () (add-hook 'window-configuration-change-hook 'org-agenda-align-tags nil t)))
         (org-agenda-mode . hl-line-mode))
  :config (add-to-list 'org-agenda-after-show-hook 'org-show-entry)
  (let ((active-project-match "-INBOX/PROJECT"))

    (gsetq org-stuck-projects
           `(,active-project-match ("NEXT")))

    (gsetq
     org-agenda-compact-blocks t
     org-agenda-sticky t
     org-agenda-start-on-weekday nil
     org-agenda-span 'day
     org-agenda-include-diary nil
     org-agenda-sorting-strategy
     '((agenda habit-down time-up user-defined-up effort-up category-keep)
       (todo category-up effort-up)
       (tags category-up effort-up)
       (search category-up))
     org-agenda-window-setup 'current-window
     org-agenda-custom-commands
     `(("N" "Notes" tags "NOTE"
        ((org-agenda-overriding-header "Notes")
         (org-tags-match-list-sublevels t)))
       ("g" "GTD"
        ((agenda "" nil)
         (tags "INBOX"
               ((org-agenda-overriding-header "Inbox")
                (org-tags-match-list-sublevels nil)))
         (stuck ""
                ((org-agenda-overriding-header "Stuck Projects")
                 (org-agenda-tags-todo-honor-ignore-options t)
                 (org-tags-match-list-sublevels t)
                 (org-agenda-todo-ignore-scheduled 'future)))
         (tags-todo "-INBOX"
                    ((org-agenda-overriding-header "Next Actions")
                     (org-agenda-tags-todo-honor-ignore-options t)
                     (org-agenda-todo-ignore-scheduled 'future)
                     (org-agenda-skip-function
                      '(lambda ()
                         (or (org-agenda-skip-subtree-if 'todo '("HOLD" "WAITING"))
                             (org-agenda-skip-entry-if 'nottodo '("NEXT")))))
                     (org-tags-match-list-sublevels t)
                     (org-agenda-sorting-strategy
                      '(todo-state-down effort-up category-keep))))
         (tags-todo ,active-project-match
                    ((org-agenda-overriding-header "Projects")
                     (org-tags-match-list-sublevels t)
                     (org-agenda-sorting-strategy
                      '(category-keep))))
         (tags-todo "-INBOX/-NEXT"
                    ((org-agenda-overriding-header "Orphaned Tasks")
                     (org-agenda-tags-todo-honor-ignore-options t)
                     (org-agenda-todo-ignore-scheduled 'future)
                     (org-agenda-skip-function
                      '(lambda ()
                         (or (org-agenda-skip-subtree-if 'todo '("PROJECT" "HOLD" "WAITING" "DELEGATED"))
                             (org-agenda-skip-subtree-if 'nottododo '("TODO")))))
                     (org-tags-match-list-sublevels t)
                     (org-agenda-sorting-strategy
                      '(category-keep))))
         (tags-todo "/WAITING"
                    ((org-agenda-overriding-header "Waiting")
                     (org-agenda-tags-todo-honor-ignore-options t)
                     (org-agenda-todo-ignore-scheduled 'future)
                     (org-agenda-sorting-strategy
                      '(category-keep))))
         (tags-todo "/DELEGATED"
                    ((org-agenda-overriding-header "Delegated")
                     (org-agenda-tags-todo-honor-ignore-options t)
                     (org-agenda-todo-ignore-scheduled 'future)
                     (org-agenda-sorting-strategy
                      '(category-keep))))
         (tags-todo "-INBOX"
                    ((org-agenda-overriding-header "On Hold")
                     (org-agenda-skip-function
                      '(lambda ()
                         (or (org-agenda-skip-subtree-if 'todo '("WAITING"))
                             (org-agenda-skip-entry-if 'nottodo '("HOLD")))))
                     (org-tags-match-list-sublevels nil)
                     (org-agenda-sorting-strategy
                      '(category-keep))))))))))

Org Bullets

(straight-use-package 'org-bullets)
(use-package org-bullets
  :preface
  (defun nasy/org-bullets-mode ()
    (org-bullets-mode 1))
  :hook ((org-mode . nasy/org-bullets-mode))
  :init (gsetq org-bullets-bullet-list
               '(;;; Large
                 "♥"
                 "✿"
                 "❀"
                 "◉"
                 "✸"
                 "•")))
                 ;; ♥ ● ○ ◇ ✚ ✜ ☯ ◆ ♠ ♣ ♦ ☢ ❀ ◆ ◖ ▶
                 ;;; Small
                 ;; ► • ★ ▸

Org Capture

(use-package org-capture
  :defer t
  :init
  (unless (boundp 'org-capture-templates)
    (defvar org-capture-templates nil))

  (add-to-list 'org-capture-templates '("t" "Tasks"))

  (add-to-list 'org-capture-templates
               '("tr" "Book Reading Task" entry
                 (file+olp "~/notes/task.org" "Reading" "Book")
                 "* TODO %^{book name}\n%u\n%a\n" :clock-in t :clock-resume t))

  (add-to-list 'org-capture-templates
               '("tw" "Work Task" entry
                 (file+headline "~/notes/task.org" "Work")
                 "* TODO %^{task name}\n%u\n%a\n" :clock-in t :clock-resume t))

  (add-to-list 'org-capture-templates
               '("T" "Thoughts" entry
                 (file "~/notes/thoughts.org")
                 "* %t - %^{heading}\n\n%?"))

  (add-to-list 'org-capture-templates
               '("j" "Journal" entry
                 (file "~/notes/journal.org")
                 "* %U - %^{heading}\n  %?"))

  (add-to-list 'org-capture-templates
               '("i" "Inbox" entry
                 (file "~/notes/inbox.org")
                 "* %U - %^{heading} %^g\n %?\n"))

  (add-to-list 'org-capture-templates
               '("n" "Notes" entry
                 (file "~/notes/notes.org")
                 "* %^{heading} %t %^g\n  %?\n")))

Org Cliplink

(straight-use-package 'org-cliplink)

Org clock

(use-package org-clock
  :preface
  (defun show-org-clock-in-header-line ()
    "Show the clocked-in task in header line"
    (setq-default header-line-format '((" " org-mode-line-string ""))))

  (defun hide-org-clock-from-header-line ()
    "Hide the clocked-in task from header line"
    (setq-default header-line-format nil))
  :init
  (gsetq org-clock-persist t
         org-clock-in-resume t
         ;; Save clock data and notes in the LOGBOOK drawer
         org-clock-into-drawer t
         ;; Save state changes in the LOGBOOK drawer
         org-log-into-drawer t
         ;; Removes clocked tasks with 0:00 duration
         org-clock-out-remove-zero-time-clocks t
         ;; Show clock sums as hours and minutes, not "n days" etc.
         org-time-clocksum-format
         '(:hours "%d" :require-hours t :minutes ":%02d" :require-minutes t))
  :hook ((org-clock-in . show-org-clock-in-header-line)
         ((org-clock-out . org-clock-cancel) . hide-org-clock-from-header))
  :bind (:map org-clock-mode-line-map
             ([header-line mouse-2] . org-clock-goto)
             ([header-line mouse-1] . org-clock-menu))
  :config
  (when (and *is-a-mac* (file-directory-p "/Applications/org-clock-statusbar.app"))
    (add-hook 'org-clock-in-hook
              (lambda () (call-process "/usr/bin/osascript" nil 0 nil "-e"
                                  (concat "tell application \"org-clock-statusbar\" to clock in \""
                                          org-clock-current-task "\""))))
    (add-hook 'org-clock-out-hook
              (lambda () (call-process "/usr/bin/osascript" nil 0 nil "-e"
                                  "tell application \"org-clock-statusbar\" to clock out")))))

Org Extra Jar – ob-ditaa & ob-plantuml

Include ob-ditaa and ob-plantuml

(use-package org
  :defer t
  :preface
  (defun grab-ditaa (url jar-name)
    "Download URL and extract JAR-NAME as `org-ditaa-jar-path'."
    (message "Grabbing " jar-name " for org.")
    (let ((zip-temp (make-temp-name (no-littering-expand-var-file-name "emacs-ditaa"))))
      (unwind-protect
          (progn
            (when (executable-find "unzip")
              (url-copy-file url zip-temp)
              (shell-command (concat "unzip -p " (shell-quote-argument zip-temp)
                                     " " (shell-quote-argument jar-name) " > "
                                     (shell-quote-argument org-ditaa-jar-path)))))
        (when (file-exists-p zip-temp)
          (delete-file zip-temp)))))
  :config
  (unless (and (boundp 'org-ditaa-jar-path)
               (file-exists-p org-ditaa-jar-path))
    (let ((jar-name "ditaa0_9.jar")
          (url "http://jaist.dl.sourceforge.net/project/ditaa/ditaa/0.9/ditaa0_9.zip"))
      (setq org-ditaa-jar-path (no-littering-expand-var-file-name jar-name))
      (unless (file-exists-p org-ditaa-jar-path)
        (grab-ditaa url jar-name))))

  (let ((jar-name "plantuml.jar")
        (url "http://jaist.dl.sourceforge.net/project/plantuml/plantuml.jar"))
    (setq org-plantuml-jar-path (no-littering-expand-var-file-name jar-name))
    (unless (file-exists-p org-plantuml-jar-path)
      (url-copy-file url org-plantuml-jar-path))))

Org PDF view

(straight-use-package 'org-pdfview)

Org Pomodoro

(use-package org-pomodoro
  :defer t
  :init (gsetq org-pomodoro-keep-killed-pomodoro-time t)
  :bind (:map org-agenda-mode-map
              ("P" . org-pomodoro)))

Org Toc

(straight-use-package 'toc-org)

Org Wc

(straight-use-package 'org-wc)

UI

Font

Emojify and all-the-icons
(straight-use-package 'emojify)
(use-package emojify
  :commands emojify-mode
  :hook ((after-init . global-emojify-mode))
  :init (gsetq emojify-emoji-styles '(unicode github)
               emojify-display-style 'unicode))

(straight-use-package 'all-the-icons)
(use-package all-the-icons
  :init (gsetq inhibit-compacting-font-caches t))
cn-fonts

https://github.com/tumashu/cnfonts

I use cn-fonts, you can see my example cnfonts profile here

This example profile will automatically generate to etc/cnfonts/nasy-profile.el.

But disabled for it's tooo slow.

;; (use-package cnfonts
;;   :disabled t
;;   :straight t
;;   :init
;;   (gsetq cnfonts-directory (no-littering-expand-etc-file-name "cnfonts"))
;;   :hook ((after-init . cnfonts-enable))
;;   :config
;;   (defun nasy/set-symbol-fonts (fontsize-list)
;;     "Set symbol fonts with FONTSIZE-LIST."
;;     (let* ((fontname "Fira Code Symbol")
;;            (fontsize (nth 0 fontsize-list))
;;            (fontspec (font-spec :name fontname
;;                                 :size fontsize
;;                                 :weight 'normal
;;                                 :slant 'normal)))
;;       (if (cnfonts--fontspec-valid-p fontspec)
;;           (set-fontset-font t '(#Xe100 . #Xe16f) fontspec)
;;         (message "Font %S not exists!" fontname))))
;;   (defun nasy/set-symbol-extra-fonts (fontsize-list)
;;     "Set extra symbol fonts with FONTSIZE-LIST."
;;     (let* ((fontname "Arial")
;;            (fontsize (nth 0 fontsize-list))
;;            (fontspec (font-spec :name fontname
;;                                 :size fontsize
;;                                 :weight 'normal
;;                                 :slant 'normal)))
;;       (if (cnfonts--fontspec-valid-p fontspec)
;;           (set-fontset-font t '(#X1d400 . #X1d744) fontspec)
;;         (message "Font %S not exists!" fontname))))
;;   (add-hook #'cnfonts-set-font-finish-hook #'nasy/set-symbol-fonts)
;;   (add-hook #'cnfonts-set-font-finish-hook #'nasy/set-symbol-extra-fonts))
set fonts
(defun nasy/set-font ()
  "Nasy set font"
  (interactive)
  (set-face-attribute
   'default nil
   :font (font-spec :name   *font*
                    :weight *font-weight*
                    :size   *font-size*))

  (when (display-graphic-p)
    (dolist (charset '(kana han symbol cjk-misc bopomofo))
      (set-fontset-font
       (frame-parameter nil 'font)
       charset
       (font-spec :name   *font-cjk*
                  :weight *font-weight-cjk*
                  :size   *font-size-cjk*)))))

(nasy/set-font)

Main Theme

I use doom-themes.

Doom-themes
(straight-use-package 'doom-themes)
(use-package doom-themes
  :init (gsetq doom-dracula-brighter-comments t
               doom-dracula-colorful-headers  t
               doom-dracula-comment-bg        t)
  :config
  (with-eval-after-load 'treemacs
    (doom-themes-treemacs-config))
  (doom-themes-visual-bell-config)
  (with-eval-after-load 'org
    (doom-themes-org-config)))
Darktooth-theme
(straight-use-package 'darktooth-theme)
(use-package darktooth-theme
  :config
  (darktooth-modeline))
Soothe-theme
(straight-use-package 'soothe-theme)
Load Theme
(load-theme *theme* t)

Mode Line

(straight-use-package 'nyan-mode)
(use-package nyan-mode
  :init (gsetq nyan-animate-nyancat t
               nyan-bar-length 16
               nyan-wavy-trail t)
  :hook ((after-init . nyan-mode)))
(straight-use-package 'minions)
(use-package minions
  :hook ((after-init . minions-mode))
  :init (gsetq minions-mode-line-lighter "✬"))
(straight-use-package 'doom-modeline)
(use-package doom-modeline
  :hook ((after-init . doom-modeline-mode))
  :init (gsetq
         doom-modeline-height                   25
         doom-modeline-bar-width                3
         doom-modeline-buffer-file-name-style   'relative-from-project
         doom-modeline-icon                     t
         doom-modeline-major-mode-icon          t
         doom-modeline-major-mode-color-icon    t
         doom-modeline-buffer-state-icon        t
         doom-modeline-buffer-modification-icon t
         doom-modeline-minor-modes              t
         doom-modeline-enable-word-count        t
         doom-modeline-checker-simple-format    nil
         doom-modeline-vcs-max-length           12
         doom-modeline-persp-name               t
         doom-modeline-lsp                      t
         doom-modeline-github                   t
         doom-modeline-github-interval          (* 30 60)

         doom-modeline-env-version       t
         doom-modeline-env-enable-python t
         doom-modeline-env-enable-ruby   t
         doom-modeline-env-enable-perl   t
         doom-modeline-env-enable-go     t
         doom-modeline-env-enable-elixir t
         doom-modeline-env-enable-rust   t

         doom-modeline-env-python-executable "python"
         doom-modeline-env-ruby-executable   "ruby"
         doom-modeline-env-perl-executable   "perl"
         doom-modeline-env-go-executable     "go"
         doom-modeline-env-elixir-executable "iex"
         doom-modeline-env-rust-executable   "rustc"

         doom-modeline-mu4e        t
         doom-modeline-irc         t
         doom-modeline-irc-stylize 'identity)
  :config
  (doom-modeline-def-segment nasy/time
    "Time"
    (when (doom-modeline--active)
      (propertize
       (format-time-string " %b %d, %Y - %H:%M ")
       'face (when (doom-modeline--active) `(:foreground "#1b335f" :background "#fab95b")))))

  ;; Remove
  ;; modals (evil, god, ryo and xah-fly-keys, etc.), parrot
  ;; buffer-encoding
  ;; Add
  ;; nasy/time
  (doom-modeline-def-modeline 'main
    '(bar workspace-name window-number matches buffer-info remote-host buffer-position selection-info)
    '(misc-info persp-name lsp irc mu4e github debug battery minor-modes input-method major-mode process vcs checker " " process nasy/time))

  (doom-modeline-def-modeline 'minimal
    '(bar matches " " buffer-info)
    '(media-info major-mode " " nasy/time))

  (doom-modeline-def-modeline 'special
    '(bar window-number matches buffer-position selection-info)
    '(misc-info lsp irc-buffers debug battery minor-modes input-method major-mode process nasy/time))

  (doom-modeline-def-modeline 'media
    '(bar window-number buffer-size buffer-info)
    '(misc-info media-info major-mode process vcs " " nasy/time))

  (doom-modeline-def-modeline 'pdf
    '(bar window-number buffer-size buffer-info pdf-pages)
    '(misc-info " " major-mode process vcs " " nasy/time))

  (doom-modeline-def-modeline 'project
    '(bar window-number " " buffer-default-directory)
    '(misc-info mu4e github debug battery " " major-mode " " process nasy/time))

  ;; Change behaviors
  (defun nasy/doom-modeline-update-buffer-file-name (&rest _)
    "Update buffer file name in mode-line."
    (setq doom-modeline--buffer-file-name
          (if buffer-file-name
              (doom-modeline-buffer-file-name)
            (if (string-prefix-p "*Org Src" (format-mode-line "%b"))
                ""
              (propertize "%b"
                          'face (if (doom-modeline--active)
                                    'doom-modeline-buffer-file
                                  'mode-line-inactive)
                          'help-echo "Buffer name
    mouse-1: Previous buffer\nmouse-3: Next buffer"
                          'local-map mode-line-buffer-identification-keymap)))))
  (advice-add #'doom-modeline-update-buffer-file-name :override #'nasy/doom-modeline-update-buffer-file-name))

Dashboard

(straight-use-package 'dashboard)
(use-package dashboard
  :bind
  ;; https://github.com/rakanalh/emacs-dashboard/issues/45
  :diminish (dashboard-mode page-break-lines-mode)
  :hook ((dashboard-mode . (lambda () (gsetq-local tab-width 1))))
  :init
  (general-define-key
   :keymaps 'dashboard-mode-map
   "<down-mouse-1>" nil
   "<mouse-1>"      'widget-button-click
   "<mouse-2>"      'widget-button-click
   "<up>"           'dashboard-previous-line
   "<down>"         'dashboard-next-line)
  (gsetq dashboard-startup-banner    'official
         dashboard-center-content    t
         dashboard-show-shortcuts    t
         dashboard-set-heading-icons t
         dashboard-set-file-icons    t
         dashboard-set-init-info     t
         show-week-agenda-p          t
         dashboard-items '((recents   . 10)
                           (bookmarks . 5)
                           ;;(registers . 5 )
                           ;;(agenda    . 5)
                           (projects  . 5)))
  (dashboard-setup-startup-hook)
  :config
  (advice-add 'dashboard-next-line :after #'(lambda (&rest r) (forward-char 2)))
  (advice-add 'widget-forward :after #'(lambda (&rest r) (forward-char 2))))

Epilogue

(run-hooks 'nasy/config-before-hook)

(setq custom-file (no-littering-expand-etc-file-name "custom.el"))

(when (file-exists-p custom-file)
  (load custom-file))

(when *server*
  (server-start))
;;; init.el ends here

Epilogue

Hope you enjoy it.

Date: 2019-04-19 Fri 00:00

Author: Nasy

Created: 2019-11-25 Mon 00:33

Validate