Emacs Configuration


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
Complete Literate Configuration


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




  • Emacs
  • git
  • make


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.


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 ):

 ;; 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)
(provide 'user-config-example)


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.


  • 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.



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

The Configuration

See the complete literate config here:



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 .


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.

(setq straight-recipes-gnu-elpa-use-mirror t
      straight-repository-branch           "develop"
      straight-check-for-modifications     'live
      straight-vc-git-default-clone-depth  1)

(defvar bootstrap-version)

(let ((bootstrap-file
       (expand-file-name "straight/repos/straight.el/bootstrap.el" user-emacs-directory))
      (bootstrap-version 5))
  (unless (file-exists-p bootstrap-file)
         'silent 'inhibit-cookies)
      (goto-char (point-max))
  (load bootstrap-file nil 'nomessage))

Some packages need to re-register, due to they cannot only do shadow-clone.

   '(magit :type git :host github
           :repo "magit/magit"
           :depth full))

   '(git-commit :type git :host github
                :repo "magit/magit"
                :depth full))

At the same time, I use use-package to manage packages in one file.

(straight-use-package 'use-package)

Garbage Collection

Adjust garbage collection thresholds during startup, and thereafter

(let ((normal-gc-cons-threshold (* 128 1024 1024))
      (init-gc-cons-threshold (* 256 1024 1024)))
  (setq gc-cons-threshold init-gc-cons-threshold)
  (add-hook #'emacs-startup-hook
            (lambda () (setq gc-cons-threshold normal-gc-cons-threshold))))

(add-hook 'focus-out-hook #'garbage-collect)


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

Expand load-path

(add-to-list 'load-path (expand-file-name "lisp"   user-emacs-directory))
(add-to-list 'load-path (expand-file-name "custom" user-emacs-directory))

No Littering

(use-package no-littering
  :straight t)

Key Definition

(use-package general
  :straight t
  (defalias 'gsetq #'general-setq)
  (defalias 'gsetq-local #'general-setq-local)
  (defalias 'gsetq-default #'general-setq-default))

Load Org

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

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


Load Custom Config

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 Configs
(defgroup nasy nil
  "Nasy Emacs Custom Configurations."
  :group 'emacs)

(defcustom lisp-modes-hooks '(cider-repl-mode-hook
  "List of lisp-related modes hooks."
  :type '(repeat symbol)
  :group 'nasy)

(defcustom *clangd* (or (executable-find "clangd")  ;; usually
                       (executable-find "/usr/local/opt/llvm/bin/clangd"))  ;; macOS
  "Clangd path.  If nil, will not use clangd."
  :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* (or (executable-find "rls")
                     (executable-find "~/.cargo/bin/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)
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."
    (unless (and *is-a-mac*
macOS Key Bindings
(when *is-a-mac*
  (gsetq mac-option-modifier  'meta
         mac-command-modifier 'hyper
         mac-right-command-modifier 'control)

   "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*
                 :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"))))
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))
Default Settings
  • Company
     company-idle-delay .5)
  • Cursor
      blink-cursor-interval .6
      blink-matching-paren  t
      cursor-in-non-selected-windows t)
    (blink-cursor-mode t)
  • Languages
     haskell-stylish-on-save nil
     blacken-line-length     80
     lsp-rust-rls-command    '("rls"))
  • Pandoc
     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
     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
     shell-file-name "/bin/zsh")
  • Start
     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
     fill-column                    80
     visual-fill-column-width       100
     word-wrap                      t
     highlight-indent-guides-method 'column
     tab-width                      8
     tooltip-delay                  1.5)
  • Whitespace
     whitespace-line-column 80
     whitespace-style       '(face spaces tabs newline
                              space-mark tab-mark newline-mark
                              lines-tail empty))
   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."
   ;; 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."
  (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)
  (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)
  (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)))
(add-hook 'nasy/config-after-hook #'nasy/set-face)
Load User Custom
(require 'user-config-example nil t)
(require 'user-config nil t)
(use-package async
  :straight t
  (dired-async-mode            1)
  (async-bytecomp-package-mode 1))

(use-package auto-compile
  :demand   t
  :straight t

(setq-default compilation-scroll-output t)

(use-package alert
  :defer    t
  :straight t
  (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))))
        (alert (concat "Compilation " result)
               :buffer buf
               :category 'compilation)))))

(use-package compile
  :defer t
  (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))
             (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
  :after    compile
  :straight t
  :hook ((compilation-filter . colourise-compilation-buffer))
  (defun colourise-compilation-buffer ()
    (when (eq major-mode 'compilation-mode)
      (ansi-color-apply-on-region compilation-filter-start (point-max)))))
Auto Compression
(require 'jka-compr)
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)))
        (apply orig args)
      (message "Desktop restored in %.2fms"
               (benchmark-init/time-subtract-millis (current-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)))
        (apply orig ver filename args)
      (message "Desktop: %.2fms to restore %s"
               (benchmark-init/time-subtract-millis (current-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-autosave-interval 60)

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

(use-package session
  :defer    t
  :straight t
  :hook ((after-init . session-initialize))
  (setq 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
        (append '((comint-input-ring        . 50)
                  (compile-history          . 30)
                  (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)
                  (search-ring              . 20)
                  (shell-command-history    . 50)
Auto Save (Super Save)

I use super save to auto save files.

(use-package super-save
  :straight t
  :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
               '(ibuffer other-window windmove-up windmove-down windmove-left windmove-right next-buffer previous-buffer)))
Text Scale
(use-package default-text-scale
  :defer    t
  :straight t)
Custom Functions
Reload the init-file
(defun radian-reload-init ()
  "Reload init.el."
    (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."
  (message "Evaluating %s..." (buffer-name))
    (if (null buffer-file-name)
      (when (string= buffer-file-name user-init-file)
      (load-file buffer-file-name)))
  (message "Evaluating %s... done." (buffer-name)))
Insert Date
(defun nasy:insert-current-date ()
  "Insert current date."
  (insert (shell-command-to-string "echo -n $(date +'%b %d, %Y')")))

(defun nasy:insert-current-filename ()
  "Insert current buffer filename."
  (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))
        (round (* 0.02 (x-display-pixel-height)))))
Toogle Dvorak Key Bindings
(defun nasy/toogle-dvorak ()
  "Toogle dvorak key bindings."
  (if (not *dvorak*)
         :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."))
         :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."))))


Ace Window
(use-package ace-window
  :defer    t
  :straight t
  :bind (("M-o" . ace-window))
   'aw-leading-char-face nil
   :foreground "deep sky blue"
   :weight 'bold
   :height 3.0)
   '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
         '((?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 ()
                   (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))
(use-package switch-window
  :straight t
  :init (setq-default switch-window-shortcut-style 'alphabet
                      switch-window-timeout nil)
  ;; 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."
    (if (and winner-mode
             (equal (selected-window) (next-window)))

  (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."
    (let ((other-buffer (and (next-window) (window-buffer (next-window)))))
      (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."
    (let ((other-buffer (and (next-window) (window-buffer (next-window)))))
      (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."
    (if (eq last-command 'nasy-split-window)
          (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)))

   :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))


(use-package dashboard
  :after    org
  :straight t
  ;; https://github.com/rakanalh/emacs-dashboard/issues/45
  (:map dashboard-mode-map
        ("<down-mouse-1>" . nil)
        ("<mouse-1>"      . widget-button-click)
        ("<mouse-2>"      . widget-button-click)
        ("<up>"           . widget-backward)
        ("<down>"         . widget-forward))
  :diminish (dashboard-mode page-break-lines-mode)
  :hook ((dashboard-mode . (lambda () (gsetq-local tab-width 1))))
  (gsetq dashboard-startup-banner 'official
         dashboard-center-content t
         show-week-agenda-p       t
         dashboard-items '((recents   . 10)
                           (bookmarks . 5)
                           (projects  . 5)))
                           ;; (agenda    . 5 )
                           ;; (registers . 5 )

  ;; Thanks https://github.com/seagle0128/.emacs.d/blob/master/lisp/init-dashboard.el
  ;; Add heading icons
  (defun dashboard-insert-heading-icon (heading &optional _shortcut)
    "Add heading icons to dashboard."
    (when (display-graphic-p)
      ;; Load `all-the-icons' if it's unavailable
      (unless (featurep 'all-the-icons)
        (require 'all-the-icons nil t))

      (insert (cond
               ((string-equal heading "Recent Files:")
                (all-the-icons-octicon "history" :height 1.2 :v-adjust 0.0 :face 'dashboard-heading))
               ((string-equal heading "Bookmarks:")
                (all-the-icons-octicon "bookmark" :height 1.2 :v-adjust 0.0 :face 'dashboard-heading))
               ((string-equal heading "Projects:")
                (all-the-icons-octicon "file-directory" :height 1.2 :v-adjust 0.0 :face 'dashboard-heading))))
      (insert " ")))
  (advice-add #'dashboard-insert-heading :before #'dashboard-insert-heading-icon)

  ;; Add file icons
  ;; MUST redefine the sections because of the macro `dashboard-insert-section-list'
  (defmacro dashboard-insert-section-list (section-name list action &rest rest)
    "Insert into SECTION-NAME a LIST of items, expanding ACTION and passing REST to widget creation."
    `(when (car ,list)
       (mapc (lambda (el)
               (let ((widget nil))
                 (insert "\n    ")
                 (when (display-graphic-p)
                   (insert (when-let ((path (car (last (split-string ,@rest " - ")))))
                             (if (file-directory-p path)
                                  ((and (fboundp 'tramp-tramp-file-p)
                                      (tramp-tramp-file-p default-directory))
                                   (all-the-icons-octicon "file-directory" :height 1.0 :v-adjust 0.01))
                                  ((file-symlink-p path)
                                   (all-the-icons-octicon "file-symlink-directory" :height 1.0 :v-adjust 0.01))
                                  ((all-the-icons-dir-is-submodule path)
                                   (all-the-icons-octicon "file-submodule" :height 1.0 :v-adjust 0.01))
                                  ((file-exists-p (format "%s/.git" path))
                                   (all-the-icons-octicon "repo" :height 1.1 :v-adjust 0.01))
                                  (t (let ((matcher (all-the-icons-match-to-alist path all-the-icons-dir-icon-alist)))
                                       (apply (car matcher) (list (cadr matcher) :v-adjust 0.01)))))
                               (all-the-icons-icon-for-file (file-name-nondirectory path)))))
                   (insert "\t"))
                 (setq widget
                       (widget-create 'push-button
                                      :action ,action
                                      :mouse-face 'highlight
                                      :button-prefix ""
                                      :button-suffix ""
                                      :format "%[%t%]"

  (defmacro dashboard-insert-shortcut (shortcut-char
                                         &optional no-next-line)
      "Insert a shortcut SHORTCUT-CHAR for a given SEARCH-LABEL.
Optionally, provide NO-NEXT-LINE to move the cursor forward a line."
         (eval-when-compile (defvar dashboard-mode-map))
         (let ((sym (make-symbol (format "Jump to \"%s\"" ,search-label))))
           (fset sym (lambda ()
                       (unless (search-forward ,search-label (point-max) t)
                         (search-backward ,search-label (point-min) t))
                       ,@(unless no-next-line
                           '((forward-line 1)))
                       (if (display-graphic-p) (widget-forward 1))))
           (eval-after-load 'dashboard
             (define-key dashboard-mode-map ,shortcut-char sym)))))

  ;; Recentf
  (defun dashboard-insert-recents (list-size)
    "Add the list of LIST-SIZE items from recently edited files."
     "Recent Files:"
     `(lambda (&rest ignore) (find-file-existing ,el))
     (abbreviate-file-name el)))

  ;; Bookmarks
  (defun dashboard-insert-bookmarks (list-size)
    "Add the list of LIST-SIZE items of bookmarks."
    (require 'bookmark)
     (dashboard-subseq (bookmark-all-names)
                       0 list-size)
     `(lambda (&rest ignore) (bookmark-jump ,el))
     (let ((file (bookmark-get-filename el)))
       (if file
           (format "%s - %s" el (abbreviate-file-name file))

  ;; Projectile
  (defun dashboard-insert-projects (list-size)
    "Add the list of LIST-SIZE items of projects."
    (require 'projectile)
     (dashboard-subseq (projectile-relevant-known-projects)
                       0 list-size)
     `(lambda (&rest ignore) (projectile-switch-project-by-name ,el))
     (abbreviate-file-name el))))


Disable Mouse
(use-package disable-mouse
  :straight t
   "<mouse-4>" (lambda! (scroll-down 1))
   "<mouse-5>" (lambda! (scroll-up 1))))
(setq enable-recursive-minibuffers t)


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

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

(use-package cmd-to-echo
  :defer    t
  :straight t)

(use-package command-log-mode
  :defer    t
  :straight t)

(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)

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

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

  (defun get-call-process-args-from-shell-command (command)
        (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)

  (use-package noflet :straight t)

  (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 (setq shell-command-switch "-ic")
  (when nil (message "PATH: %s, INFO: %s" (getenv "PATH")
                     (getenv "ENVIRONMENT_SETUP_DONE"))
        (setq exec-path-from-shell-debug t))
  (setq exec-path-from-shell-arguments (list "-l"))
  (setq 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")
  (add-to-list 'exec-path "~/.pyenv/shims/"))

Emacs libvterm intergration


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


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

;; Editor


(use-package diminish
  :demand   t
  :straight t)


(use-package flx
  :defer    t
  :straight t)

Advance Words Count

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


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

Auto Insert

(use-package autoinsert
    '("\\.py" . "Python Language")
    '("Python Language"
      "#!/usr/bin/env python3\n"
      "# -*- coding: utf-8 -*-\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"
      "There are more things in heaven and earth, Horatio, than are dreamt.\n"
      " --  From \"Hamlet\"\n"

    '("\\.hs" . "Haskell Language")
    '("Haskell Language"
      " 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"
      "There are more things in heaven and earth, Horatio, than are dreamt.\n"
      "   -- From \"Hamlet\"\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"

Beacon (Disabled)

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


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

Carbon Now sh

Emacs to carbon.now.sh integration.


Try: M-x carbon-now-sh RET

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

Cheat Sh

(use-package cheat-sh
  :defer    t
  :straight t)


(use-package company
  :straight t
  (gsetq company-minimum-prefix-length .2
         company-require-match nil
         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-C-/" . company-complete)
         :map company-mode-map
         ("M-/"   . company-complete)
         :map company-active-map
         ("M-/"   . company-complete)
         ("<tab>" . company-other-backend)
         ("C-n"   . company-select-next)
         ("C-p"   . company-select-previous))
  (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
          (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
          (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)

  (diminish 'company-mode "CMP")
  (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))
      (append (if (consp backends)
                (list backends))
              '(:with company-yasnippet))))
  ;; add yasnippet to all backends
  (gsetq company-backends
        (mapcar #'company-backend-with-yas company-backends)))
Company Try Hard
(use-package company-try-hard
  :straight t
  :bind (:map company-active-map
         ("C-z" . company-try-hard)))
Company Quickhelp
(use-package company-quickhelp
  :after company
  :straight t
  :bind (:map company-active-map
              ("C-c h" . company-quickhelp-manual-begin))
  :ghook #'after-init-hook
  :init (setq pos-tip-use-relative-coordinates t))
Company Math
(use-package company-math
  :defer    t
  :straight t)
Company Flx
(use-package company-flx
  :straight t
  :after company
  :ghook #'after-init-hook)
Company Box
(when *c-box*
  (use-package company-box
    :defer    t
    :straight t
    :after (all-the-icons company)
    (setq company-box-icons-alist 'company-box-icons-all-the-icons)
    :ghook 'company-mode-hook
    (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
           (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


(use-package dash
  :defer    t
  :straight t)

Dash Functional

(use-package dash-functional
  :defer    t
  :straight t)


(use-package dired
  (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)))
(use-package diredfl
  :after dired
  :straight t
  :hook ((after-init . diredfl-global-mode)))
(use-package uniquify
  :init  ;; nicer naming of buffers for files with identical names
  (setq uniquify-buffer-name-style   'reverse
        uniquify-separator           " • "
        uniquify-after-kill-buffer-p t
        uniquify-ignore-buffers-re   "^\\*"))
Diff-hl (only for dired)
(use-package diff-hl
  :after dired
  :straight t
  :hook ((dired-mode . diff-hl-dired-mode)
         (magit-post-refresh . diff-hl-magit-post-refresh)))
Dired Hacks Utils
(use-package dired-hacks-utils
  :after    dired
  :straight t)
Dired Filter
(use-package dired-filter
  :after    dired
  :straight t
  :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
                   (directory . ".git")
                   (file . ".gitignore"))
                   (extension . "pdf"))
                   (extension "tex" "bib"))
                   (extension "c" "cpp" "hs" "rb" "py" "r" "cs" "el" "lisp" "html" "js" "css"))
                   (extension "md" "rst" "txt"))
                   (extension . "org"))
                   (extension "zip" "rar" "gz" "bz2" "tar"))
                   (extension "jpg" "JPG" "webp" "png" "PNG" "jpeg" "JPEG" "bmp" "BMP" "TIFF" "tiff" "gif" "GIF"))))))
Dired avfs
(when (executable-find "avfsd")
  (use-package dired-avfs
    :after    dired
    :straight t))
Dired Rainbow
(use-package dired-rainbow
  :after    dired
  :commands dired-rainbow-define dired-rainbow-define-chmod
  :straight t
  (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
(use-package dired-subtree
  :defer    t
  :straight t)

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

Easy Kill

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

Eldoc Box

Disabled by default due to it causes lots of cpu.

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

Fill Column

(use-package unfill
  :straight t
  :bind (("M-q" . unfill-toggle)))
(use-package visual-fill-column
  :straight t
  (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)))


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

(use-package flycheck-package
  :after flycheck
  :straight t
  (with-eval-after-load 'elisp-mode

Grab Mac Link

(use-package grab-mac-link
  :defer    t
  :straight t)


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

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


(use-package cl-lib-highlight
  :after lisp-mode
  :straight t
Color Identifiers Mode
(use-package color-identifiers-mode
  :straight t
  :hook ((after-init . global-color-identifiers-mode)))
(use-package hl-line
  :hook ((after-init . global-hl-line-mode)))
Highlight Indent Guides
(use-package highlight-indent-guides
  :straight t
  :init (setq highlight-indent-guides-responsive 'stack)
  :ghook '(prog-mode-hook text-mode-hook org-mode-hook))
Highlight Number
(use-package highlight-numbers
  :straight t
  :ghook '(after-init-hook prog-mode-hook text-mode-hook org-mode-hook))
(use-package rainbow-mode
  :straight t
  :hook (((after-init
           prog-mode). rainbow-mode))
  :diminish rainbow-mode)



(use-package helpful
  :straight t
  :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))


(use-package helm-config
  :defer    3
  :straight helm
  :diminish helm-mode
  :hook ((after-init . helm-mode)
         (after-init . helm-autoresize-mode))
  (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)

  (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"
         '("--colors 'match:fg:black'" "--colors 'match:bg:yellow'"))
   "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)
   :prefix "C-x c"
   "x"   'helm-register
   "g"   'helm-google-suggest
   "M-:" 'helm-eval-expression-with-eldoc)
   :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
   :keymaps 'shell-mode-map
   "C-c C-l" 'helm-comint-input-ring)
   :keymaps 'minibuffer-local-map
   "C-c C-l" 'helm-minibuffer-history)

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

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

  (defun nasy/helm ()
    (let ((helm-ff-transformer-show-only-basename nil)
      (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.
             (setq helm-source-list
                     ;; helm-source-awesome-tab-group

             (setq helm-source-list
                     ;; helm-source-awesome-tab-group
      (helm-other-buffer helm-source-list "*helm search*"))))
Helm Org
(use-package helm-org
  :defer 5
  (cl-defun helm-org-headings-in-buffer ()
    (helm :sources (helm-source-org-headings-for-files
                    (list (projectile-completing-read
                           "File to look at headings from: "
          :candidate-number-limit 99999
          :buffer "*helm org inbuffer*")))
Helm Company
(use-package helm-company
  :defer    5
  :straight t
  :bind (:map
         company-mode-map ("C-:" . helm-company)
         company-active-map ("C-:" . helm-company)))
Helm Shell
(use-package helm-eshell
  :defer 5
  :bind (:map eshell-mode-map
              ("C-c C-l" . helm-eshell-history)))
Helm Descbings
(use-package helm-descbinds
  :defer    5
  :straight t
  :hook ((after-init . helm-descbinds-mode)))
Helm Projectile
(use-package helm-projectile
  :defer    5
  :straight t
  :hook ((after-init . helm-projectile-on))
  (gsetq projectile-completion-system 'helm))
Helm Ag
(use-package helm-ag
  :defer    5
  :straight 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
(use-package helm-dash
  :defer    5
  :straight t
  :init (gsetq helm-dash-docsets-path "~/.docsets"))
Helm Ls Git
(use-package helm-ls-git
  :defer    5
  :straight t
  :bind (("C-<f6>"   . helm-ls-git-ls)
         ("C-x g"    . helm-ls-git-ls)
         ("C-x C-d"  . helm-browse-project)))


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


(use-package hydra
  :straight t
   :prefix "C-x"
   "9" 'hydra-unicode/body)
   :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)))


(use-package ibuffer
  :bind (("C-x C-b" . ibuffer))
  (gsetq ibuffer-saved-filter-groups
            ("Dired"      (mode . dired-mode))
            ("Emacs"     (or
                          (name . "^\\*dashboard\\*$" )
                          (name . "^\\*scratch\\*$"   )
                          (name . "^\\*Messages\\*$"  )
                          (name . "^\\*Backtrace\\*$" )))
            ("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
(use-package ibuffer-vc
  :after ibuffer
  :straight t)
Other settings
(use-package ibuffer
  (define-ibuffer-column size-h
    (:name "Size" :inline t)
    (file-size-human-readable (buffer-size)))
   '((mark modified read-only vc-status-mini " "
           (name 22 22 :left :elide)
           " "
           (size-h 9 -1 :right)
           " "
           (mode 12 12 :left :elide)
           " "
     (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)
           " "

imenu list

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


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


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

(use-package isearch
  ;; 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."
    (let ((sym (thing-at-point 'symbol)))
      (if sym
            (setq isearch-regexp t
                  isearch-string (concat "\\_<" (regexp-quote sym) "\\_>")
                  isearch-message (mapconcat 'isearch-text-char-description isearch-string "")
                  isearch-yank-flag t))

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

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

Link Hint

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

List Unicode Display

(use-package list-unicode-display
  :defer    t
  :straight t)


(use-package mmm-auto
  :straight mmm-mode
  :init (gsetq
         mmm-submode-decoration-level 2))

Multiple Cursors

(use-package multiple-cursors
  :straight t
  :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))
  ;; From active region to multiple cursors:
   :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

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

Paper Break Lines

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


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

(add-hook 'after-init-hook 'show-paren-mode)
(use-package smartparens-config
  :straight smartparens
  :hook ((after-init . show-smartparens-global-mode)
         (after-init . smartparens-global-mode))
  :init (gsetq sp-hybrid-kill-entire-symbol nil))
(use-package parinfer
  :straight t
  :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
(use-package rainbow-delimiters
  :straight t
  :ghook '(prog-mode-hook text-mode-hook org-src-mode-hook))
Highlight Parentheses
(use-package highlight-parentheses
  :straight t
  :init (gsetq hl-paren-highlight-adjacent t)
  :hook ((after-init . global-highlight-parentheses-mode)))

PDF Tools

(use-package pdf-tools
  :defer t
  :straight t
  (setq-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 Mode
(use-package pretty-mode
  :demand t
  :straight t
  :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

           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))
                                  ("List"   . #x1d543)  ;; 𝕃 𝕷
                                  ("list"   . #x1d55d)  ;; 𝕝 𝖑
                                  ("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)) ;; ∘

   '(:sub-and-superscripts :greek :arithmetic))

   '(:equality :ordering :ordering-double :ordering-triple
               :arrows :arrows-twoheaded :punctuation
               :logic :sets :arithmetic-double :arithmetic-triple)))
(use-package ipretty
  :defer    t
  :straight 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'."
    (-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."
   nil (--map (-let (((rgx uni-point) it))
               `(,rgx (0 (progn
                            (match-beginning 1) (match-end 1)
                            ,(concat "\t" (list uni-point)))

(defmacro pretty-fonts-set-kwds (FONT-LOCK-HOOKS-ALIST)
  "Set regex-unicode replacements to many modes(`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
    ;; 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)

    ;; 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)
   '((pretty-fonts-fira-font prog-mode-hook org-mode-hook))))


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

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

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


(use-package projectile
  :defer    t
  :straight t
  :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
                 (append '("compile_commands.json"


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


Now use amx instead of smex.

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

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


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

Symbol Overlay

(use-package symbol-overlay
  :straight t
  :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)))


(use-package treemacs
  :defer t
  :straight t
  (with-eval-after-load 'winum
    (define-key winum-keymap (kbd "M-0") #'treemacs-select-window))
  (gsetq treemacs-collapse-dirs                 (if (executable-find "python3") 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-follow-recenter-distance      0.1
         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
         (no-littering-expand-var-file-name "treemacs-persist")
         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 (executable-find "python3"))))
    (`(t . t)
     (treemacs-git-mode 'deferred))
    (`(t . _)
     (treemacs-git-mode 'simple)))
   :keymaps 'global-map
   "M-0" 'treemacs-select-window)
   :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))

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

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

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


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

Version Control

Useful Simple Packages
(dolist (package '(git-blamed
  (straight-use-package package)
  (require package nil t))
Git Modes
(use-package git-modes
  :defer    t
  :straight t)
(use-package magit
  :straight t
  :hook ((magit-popup-mode-hook . no-trailing-whitespace))
  :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 (with-eval-after-load 'magit-todos
  (when *is-a-mac* (add-hook 'magit-mode-hook (lambda () (local-unset-key [(meta h)])))))

(use-package magit-todos
  :defer    t
  :straight t)
Magit Org Todos
(use-package magit-org-todos
  :after    org
  :straight t
  :hook     ((after-init . magit-org-todos-autoinsert)))
(use-package forge
  :defer    t
  :straight t)
(use-package transient
  :straight t
  :init (gsetq transient-default-level 5))
Git Commit
(use-package git-commit
  :straight t
  :hook ((git-commit-mode . goto-address-mode)))
Git Messenger
(use-package git-messenger
  :straight t
  :init (gsetq git-messenger:show-detail t)
  :bind (:map vc-prefix-map
         ("p" . git-messenger:popup-message)))
Git Gutter
(use-package git-gutter
  :straight t
  :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
(use-package gist
  :defer    t
  :straight t)

Which Function

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

Which Key

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


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

  ;; But don't show trailing whitespace in SQLi, inf-ruby etc.
  (dolist (hook '(artist-mode-hook
    (add-hook hook #'no-trailing-whitespace))
  :diminish whitespace-mode)

(use-package whitespace-cleanup-mode
  :straight t
  (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

(use-package writeroom-mode
  :defer t
  :straight t
  (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
          (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)))))


(use-package yasnippet
  :straight t
  :hook (after-init . yas-global-mode))

(use-package yasnippet-snippets
  :defer    t
  :straight t)



(use-package bing-dict
  :straight t
  :bind (("C-c d" . bing-dict-brief))
  :init (setq bing-dict-show-thesaurus  'both
              bing-dict-vocabulary-save t
              bing-dict-cache-auto-save t
              (no-littering-expand-var-file-name "bing-dict/vocabulary.org")
              (no-littering-expand-var-file-name "bing-dict/bing-dict-save.el")))
(if *ispell*
    (use-package ispell
      (setq-default ispell-program-name   *ispell*
                    ispell-silently-savep t
                    ispell-dictionary     "english"
                    (no-littering-expand-var-file-name "ispell/dictionary"))
      (when (string-suffix-p "aspell" *ispell*)
        (setq-default ispell-extra-args '("--reverse"))))
  (message "if you want to use ispell, try\n brew install aspell\n brew install ispell"))

Simple Supported Languages

(let ((languages '(elvish-mode
      (extras    '(fish-completion
  (dolist (language languages)
    (straight-use-package language)
    (require language nil t))
  (dolist (extra extras)
    (straight-use-package extra)
    (require extra nil t)))

Language Server Protocol & Debug Adapter Protocol

(use-package lsp-mode
  :straight t
  :commands lsp
  (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)
           company-mode) . delete-company-lsp))
  :init (gsetq lsp-prefer-flymake            nil
               lsp-enable-on-type-formatting nil))
(use-package lsp-ui
  :after lsp-mode
  :straight t
  :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
  (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))
(use-package company-lsp
  :defer t
  :after (lsp-mode company)
  :straight t
  :commands company-lsp
     :with company-yasnippet)
  (gsetq company-lsp-async               t
         company-lsp-enable-recompletion t
         company-lsp-enable-snippet      t
         company-lsp-cache-candidates    nil)
  (setcdr (assq 'pyls company-lsp-filter-candidates) t))
Dap Mode
(use-package dap-mode
  :defer    t
  :straight t
  (require 'dap-python))

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

I use clangd.

(when *clangd*
  (use-package lsp-mode
    :straight t
    :hook (((c-mode c++-mode objc-mode) . lsp))
    :init (setq-default lsp-clients-clangd-executable *clangd*)))


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

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

  :gfhook '(subword-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))
  (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
                 (regexp . "\\(\\s-+\\)\\(::\\|\\)\\s-+")
                 (modes quote (haskell-mode literate-haskell-mode))))
  (add-to-list 'align-rules-list
                 (regexp . "\\(\\s-+\\)=\\s-+")
                 (modes quote (haskell-mode literate-haskell-mode))))
  (add-to-list 'align-rules-list
                 (regexp . "\\(\\s-+\\)\\(->\\|\\)\\s-+")
                 (modes quote (haskell-mode literate-haskell-mode))))
  (add-to-list 'align-rules-list
                 (regexp . "\\(\\s-+\\)\\(<-\\|\\)\\s-+")
                 (modes quote (haskell-mode literate-haskell-mode))))

  (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
    (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
(use-package lsp-haskell
  :demand   t
  :straight t
  :hook ((haskell-mode   . lsp)
         (lsp-after-open . (lambda () (add-hook 'before-save-hook #'lsp-format-buffer nil t)))
         (haskell-mode   . delete-company-lsp))
  ;; 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
(when *intero*
  (use-package intero
    :straight t
    :after haskell-mode
    :hook (haskell-mode . (lambda () (intero-global-mode 1)))
    (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*
      (add-to-list 'load-path *struct-hs-path*)
      (require 'shm)
      (setq shm-program-name *struct-hs*)
      (add-hook #'haskell-mode-hook #'structured-haskell-mode))
    (when *struct-hs*
      (message (concat "*NOTE* about 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
(use-package haskell-snippets
  :defer    t
  :straight t)


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

JavaScript & TypeScript

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


(use-package lisp-mode
  (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)))
(use-package highlight-quoted
  :defer t
  :straight t
  :hook ((emacs-lisp-mode . highlight-quoted-mode)))
(use-package elisp-def
  :straight t
  :hook (((emacs-lisp-mode ielm-mode) . elisp-def-mode)))


(use-package markdown-mode
  :defer t
  :straight t
  :mode ("INSTALL\\'"


(use-package pandoc-mode
  :defer    t
  :straight t)


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

Python Mode
(require 'python)

(use-package python-mode
  :straight t
  :commands python-mode
  :mode ("\\.py\\'" . python-mode)
  :interpreter (("python"  . python-mode)
                ("python3" . python-mode))
  ;; 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."
    (let ((proc (get-buffer-process nasy*python-buffer)))
      (unless proc
        (error "No process found"))
      (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))
       (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))
         (or (python-nav-end-of-defun)
            (end-of-line 1))

  (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
   :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)
   :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))
  (unless *blacken*
    (add-hook #'before-save-hook #'lsp-format-buffer nil t)))
;; Now you can use it in lsp.
;; NOTICE you have to config black though pyproject.toml.
(when *blacken*
  (use-package blacken
    :straight t
    :hook ((python-mode    . blacken-mode))))
(use-package py-isort
  :straight t
  :hook (before-save . py-isort-before-save))
Python Docstring
(use-package python-docstring
  :straight t
  :hook ((python-mode . python-docstring-mode)))
Sphinx Doc
(use-package sphinx-doc
  :straight t
  :hook ((python-mode . sphinx-doc-mode)))
(use-package pyimport
  :straight t
  :bind (:map python-mode-map
              ("C-c C-i" . pyimport-insert-missing)))


Include rust-mode, rls and Cargo.

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

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

Org Mode


I use org with org-plus-contrib

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

(require 'org-tempo nil t)

OX Org

Other ox-_ packages.

(straight-use-package 'ox-rst)

(with-eval-after-load 'ox
  (let ((oxs '(ox-md
    (dolist (language oxs)
      (require language nil t))))

(use-package ox-pandoc
  :after    ox
  :straight t)

Basic Configs

(use-package org
  (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:]]")
              "\\(" 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)
        (outline-previous-visible-heading 1)

  :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-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-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"
    (("AUTO" "inputenc" t
     ("T1" "fontenc" t
     ("" "graphicx" t nil)
     ("" "grffile" t nil)
     ("" "longtable" 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)
      "hyperref" t nil)
     ("" "luatexja-fontspec" t nil)
     ("" "listings" t nil)))
   org-latex-default-table-environment "longtable"
   org-latex-listings t
    ((emacs-lisp   "Lisp")
     (lisp         "Lisp")
     (clojure      "Lisp")
     (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")
     (R            "r")))
    ("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)
                        ("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)
  ;; --------
   `((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
           :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
           :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))

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

     org-agenda-compact-blocks t
     org-agenda-sticky t
     org-agenda-start-on-weekday nil
     org-agenda-span 'day
     org-agenda-include-diary nil
     '((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
     `(("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)
                      '(lambda ()
                         (or (org-agenda-skip-subtree-if 'todo '("HOLD" "WAITING"))
                             (org-agenda-skip-entry-if 'nottodo '("NEXT")))))
                     (org-tags-match-list-sublevels t)
                      '(todo-state-down effort-up category-keep))))
         (tags-todo ,active-project-match
                    ((org-agenda-overriding-header "Projects")
                     (org-tags-match-list-sublevels t)
         (tags-todo "-INBOX/-NEXT"
                    ((org-agenda-overriding-header "Orphaned Tasks")
                     (org-agenda-tags-todo-honor-ignore-options t)
                     (org-agenda-todo-ignore-scheduled 'future)
                      '(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)
         (tags-todo "/WAITING"
                    ((org-agenda-overriding-header "Waiting")
                     (org-agenda-tags-todo-honor-ignore-options t)
                     (org-agenda-todo-ignore-scheduled 'future)
         (tags-todo "/DELEGATED"
                    ((org-agenda-overriding-header "Delegated")
                     (org-agenda-tags-todo-honor-ignore-options t)
                     (org-agenda-todo-ignore-scheduled 'future)
         (tags-todo "-INBOX"
                    ((org-agenda-overriding-header "On Hold")
                      '(lambda ()
                         (or (org-agenda-skip-subtree-if 'todo '("WAITING"))
                             (org-agenda-skip-entry-if 'nottodo '("HOLD")))))
                     (org-tags-match-list-sublevels nil)

Org Bullets

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

Org Capture

(use-package org-capture
  (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

(use-package org-cliplink
  :defer    t
  :straight t)

Org clock

(use-package org-clock
  (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))
  (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.
         '(: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))
  (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
  (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"))))
            (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)))))
  (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

(use-package org-pdfview
  :defer    t
  :straight t)

Org Pomodoro

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

Org Toc

(use-package toc-org
  :defer    t
  :straight t)

Org Wc

(use-package org-wc
  :defer    t
  :straight t)


Main Theme

I use doom-themes.

(use-package doom-themes
  :straight t
  :init (gsetq doom-dracula-brighter-comments t
               doom-dracula-colorful-headers  t
               doom-dracula-comment-bg        t)
(use-package darktooth-theme
  :straight t
(use-package soothe-theme
  :defer    t
  :straight t)
Load Theme
(load-theme *theme* t)


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

(use-package all-the-icons
  :init (setq inhibit-compacting-font-caches t)
  :straight t)


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
  (gsetq cnfonts-directory (no-littering-expand-etc-file-name "cnfonts"))
  :hook ((after-init . cnfonts-enable))
  (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
 'default nil
 :font (font-spec :name "-*-OperatorMonoSSmLig Nerd Font Mono-normal-normal-normal-*-*-110-*-*-m-0-iso10646-1"
                  :weight 'normal
                  :slant 'normal
                  :size 12.0))

(when (display-graphic-p)
  (dolist (charset '(kana han symbol cjk-misc bopomofo))
     (frame-parameter nil 'font)
     (font-spec :name "-*-PingFang SC-normal-normal-normal-*-*-*-*-*-p-0-iso10646-1"
                :weight 'normal
                :slant 'normal
                :size 16.0))))

Mode Line

(use-package nyan-mode
  :straight t
  :init (setq nyan-animate-nyancat t
              nyan-bar-length 16
              nyan-wavy-trail t)
  :hook ((after-init . nyan-mode)))
(use-package minions
  :straight t
  :hook ((after-init . minions-mode))
  :init (gsetq minions-mode-line-lighter "✬"))
(use-package doom-modeline
  :straight t
  :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)
  (doom-modeline-def-segment nasy/time
    (when (doom-modeline--active)
       (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 fancy-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 fancy-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 fancy-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
            (if (string-prefix-p "*Org Src" (format-mode-line "%b"))
              (propertize "%b"
                          'face (if (doom-modeline--active)
                          '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))


(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*
;;; init.el ends here


Hope you enjoy it.

Date: 2019-04-19 Fri 00:00

Author: Nasy

Created: 2019-05-15 Wed 08:28