dyzdyz010 / emacs.d

My emacs configuration

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

Emacs Configuration

Prologue

A Straightforward Emacs Configuration Bundle.

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

NOTICE

  • This file is a literature programing source file, and generates init.el
  • Almost all in one file.
  • Use straight.el to manage packages.
  • For macOS GUI.
  • Now only tested with GNU Emacs 27.0.50 in macOS 10.14.
  • Font
    • Fira Code Symbol

Screenshots

./screenshot1.png

./screenshot2.png

./screenshot3.png

Dependencies

  • Emacs
  • git
  • make (optional)

Installation

To install, clone this repo to @@html: <span> @@ ~~/.emacs.d~ @@html: </span> @@:

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

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

Updates

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

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

  • @@html: <kbd>M-x</kbd> <kbd>straight-pull-all</kbd> <kbd>RET</kbd> @@
  • @@html: <kbd>M-x</kbd> <kbd>straight-rebuild-all</kbd> <kbd>RET</kbd> @@

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

Default Custom Configuration

This file includes all of the customizable variables of my configuration.

You can find it in @@html: <span> @@ config/nasy-config.el @@html: </span> @@

Header

;;; config.el --- User config file.                    -*- lexical-binding: t; -*-

;; Author: Nasy <nasyxx+emacs@gmail.com>

;;; Commentary:

;; Nasy's Custom Config file.

;;; Code:

Constants And Variables

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

(defconst *clangd*    (or (executable-find "clangd")  ;; usually
                          (executable-find "/usr/local/opt/llvm/bin/clangd")))  ;; macOS

(defconst *nix*       (executable-find "nix"))

(defconst *rust*      (or (executable-find "rustc")
                          (executable-find "cargo")
                          (executable-find "rustup")))
(defconst *rls*       (or (executable-find "rls")
                          (executable-find "~/.cargo/bin/rls")))

(defvar   *intero*    t)

(defconst *struct-hs* (executable-find "structured-haskell-mode"))
(defvar   *struct-hs-path* nil)

(defvar   *blacken*   nil)

(defvar   *vterm*     nil)

UI Settings

;; Theme
(defvar nasy:theme 'doom-dracula)

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

  (add-to-list 'default-frame-alist
               '(font . "OperatorMonoLig Nerd Font-14"))

  (defun stop-minimizing-window ()
  "Stop minimizing window under macOS."
  (interactive)
  (unless (and *is-a-mac*
               window-system)
    (suspend-frame)))

  (global-set-key (kbd "C-z") 'stop-minimizing-window))

Default Settings

Cursor

(setq-default
  blink-cursor-interval .6
  blink-matching-paren  t)

Visual

(setq-default
 fill-column                    80
 visual-fill-column-width       100
 word-wrap                      t
 highlight-indent-guides-method 'column
 tab-width                      8
 tooltip-delay                  1.5)

Company

(setq-default
 company-idle-delay .5)

Helm

(setq-default
 ;; brew install rg   if you'd like to use rg as my doing
 helm-ag-base-command "rg --no-heading --smart-case")

Shell

(setq-default
 shell-file-name "/bin/zsh")

Languages

(setq-default
 haskell-stylish-on-save nil
 blacken-line-length     80
 lsp-rust-rls-command    '("rls"))

Parens

(setq-default
 show-paren-style                                'expression
 sp-autoinsert-quote-if-followed-by-closing-pair t
 sp-base-key-bindings                            'paredit
 sp-show-pair-from-inside                        t)

Whitespace

(setq-default
 whitespace-line-column 80
 whitespace-style       '(face spaces tabs newline
                          space-mark tab-mark newline-mark
                          lines-tail empty))

Straight.el

;; The original one is `(find-at-startup find-when-checking) which is so slow.
;; straight-check-for-modifications '(find-at-startup find-when-checking)
(setq-default
 straight-check-for-modifications '(check-on-save find-when-checking))

Start

(setq-default
 initial-scratch-message     (concat ";; Happy hacking, " user-login-name " - Emacs ♥ you!\n\n")
 dashboard-banner-logo-title (concat ";; Happy hacking, " user-login-name " - Emacs ♥ you!\n\n")
 ;; initial-buffer-choice       #'(lambda () (get-buffer "*dashboard*"))  ;; It will cause error if you start emacs from Command line with file name
                                                                          ;; https://github.com/rakanalh/emacs-dashboard/issues/69
)

Config After initialization

(defun nasy:config-after ()
  "Set configuration need to be set after init."
  (setq-default
   helm-allow-mouse                  t
   helm-follow-mode-persistent       t
   helm-move-to-line-cycle-in-source nil
   helm-source-names-using-follow    '("Buffers" "kill-buffer" "Occur")))


(add-hook 'nasy:config-after-hook  #'nasy:config-after)

Custom Faces

(defun nasy:set-face ()
  "Set custom face."
  (set-face-attribute 'custom-comment              nil                                             :slant   'italic)
  (set-face-attribute 'font-lock-keyword-face      nil                                             :slant   'italic)
  (set-face-attribute 'show-paren-match            nil :background "#bfcfff" :foreground "#dc322f" :weight  'ultra-bold)
  (set-face-attribute 'show-paren-match-expression nil :background "#543e5c"                       :inherit 'unspecified)
  (set-face-attribute 'which-func                  nil                       :foreground "#333"))

(add-hook 'nasy:config-before-hook #'nasy:set-face)

Key Bindings

(when *is-a-mac*
  ;; cursor Movement
  (global-set-key (kbd "s-<up>")   'beginning-of-buffer)
  (global-set-key (kbd "s-<down>") 'end-of-buffer)
  ;; text Operations
  (global-set-key (kbd "M-¥")
                  (lambda ()
                    (interactive)
                    (insert "\\")))
  (global-set-key (kbd "s-<backspace>")
                  (lambda ()
                    (interactive)
                    (kill-line 0)))
)

Epoligue

(provide 'nasy-config)
;;; nasy-config.el ends here

Example Custom Configuration

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

(setq-default
 calendar-latitude           24.8801
 calendar-longitude          102.8329
 user-mail-address           "nasyxx@gmail.com"
 initial-buffer-choice       #'(lambda () (get-buffer "*dashboard*"))
 nasy:theme                  'doom-Iosvkem
 *struct-hs-path*            nil
 *vterm*                     "/Users/Nasy/src/emacs-libvterm")
(provide 'user-config)

dashboard

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

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

in your config/user-config.el.

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

NOTICE:

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

The Configuration

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

Bootstrap

In this section, the configuration needs to occur early in emacs startup.

File Header

This includes some necessary headers.

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

;; Author: Nasy <nasyxx+emacs@gmail.com>

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

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

(defvar bootstrap-version)

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

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

(straight-use-package 'use-package)

Garbage Collection

Adjust garbage collection thresholds during startup, and thereafter

(let ((normal-gc-cons-threshold (* 256 1024 1024))
      (init-gc-cons-threshold (* 512 1024 1024)))
  (setq gc-cons-threshold init-gc-cons-threshold)
  (add-hook 'after-init-hook
            (lambda ()
              (setq gc-cons-threshold normal-gc-cons-threshold))))

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

Benchmark

(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 "config" user-emacs-directory))

No Littering

(use-package no-littering
  :straight t)

Basic Configs

Compile

(use-package async
  :straight t
  :config
  (dired-async-mode            1)
  (async-bytecomp-package-mode 1))

(use-package auto-compile
  :demand   t
  :straight t
  :config
  (auto-compile-on-load-mode)
  (auto-compile-on-save-mode))

(setq-default compilation-scroll-output t)

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


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

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

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


(use-package ansi-color
  :demand   t
  :after    compile
  :straight t
  :hook ((compilation-filter . colourise-compilation-buffer))
  :config
  (defun colourise-compilation-buffer ()
    (when (eq major-mode 'compilation-mode)
      (ansi-color-apply-on-region compilation-filter-start (point-max)))))

Hooks & Custom Require

(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)))
(require 'nasy-config nil t)
(require 'user-config nil t)

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

Nice Scrolling

(setq scroll-margin                   0
      scroll-conservatively           100000
      scroll-preserve-screen-position 'always)

Text Scale

(straight-use-package 'default-text-scale)

Shell

(require 'shell)

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


(use-package command-log-mode
  :demand   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
  :preface
  ;; Non-Forking Shell Command To String
  ;; https://github.com/bbatsov/projectile/issues/1044
  ;;--------------------------------------------------------------------------

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

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

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

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

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

  (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")
  :config
  (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")
  (exec-path-from-shell-initialize))

Term

Emacs libvterm intergration

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

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

Scratch Message

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

Dashboard

(use-package dashboard
  :demand   t
  :after    org
  :straight t
  :init (setq dashboard-startup-banner 'official
              dashboard-items '((recents   . 10)
                                (bookmarks . 3 )
                                (projects  . 5 )
                                (agenda    . 5 )
                                (registers . 5 )))
  :config (dashboard-setup-startup-hook))

Window

(add-hook 'after-init-hook 'winner-mode)

(use-package switch-window
  :straight t
  :init (setq-default switch-window-shortcut-style 'alphabet
                      switch-window-timeout nil)
  :bind (("C-x o" . switch-window)))

;; When splitting window, show (other-buffer) in the new window
(defun split-window-func-with-other-buffer (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)))))

(global-set-key (kbd "C-x 2")
                (split-window-func-with-other-buffer 'split-window-vertically))
(global-set-key (kbd "C-x 3")
                (split-window-func-with-other-buffer 'split-window-horizontally))


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

(global-set-key (kbd "C-x 1") 'toggle-delete-other-windows)

Session

(setq desktop-path              (list user-emacs-directory)
      desktop-auto-save-timeout 600)
(desktop-save-mode t)
(setq desktop-save 'if-exists)


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

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


(setq-default history-length 1000)
(add-hook 'after-init-hook 'savehist-mode)


(use-package session
  :defer    t
  :straight t
  :hook ((after-init . session-initialize))
  :init
  (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
        desktop-globals-to-save
        (append '((comint-input-ring        . 50)
                  (compile-history          . 30)
                  desktop-missing-file-warning
                  (dired-regexp-history     . 20)
                  (extended-command-history . 30)
                  (face-name-history        . 20)
                  (file-name-history        . 100)
                  (grep-find-history        . 30)
                  (grep-history             . 30)
                  (ivy-history              . 100)
                  (magit-revision-history   . 50)
                  (minibuffer-history       . 50)
                  (org-clock-history        . 50)
                  (org-refile-history       . 50)
                  (org-tags-history         . 50)
                  (query-replace-history    . 60)
                  (read-expression-history  . 60)
                  (regexp-history           . 60)
                  (regexp-search-ring       . 20)
                  register-alist
                  (search-ring              . 20)
                  (shell-command-history    . 50)
                  tags-file-name
                  tags-table-list))))

Auto Save (Super Save)

I use super save to auto save files.

(use-package super-save
  :straight t
  :hook ((after-init . (lambda () (super-save-mode +1))))
  :init (setq super-save-auto-save-when-idle nil
              super-save-remote-files        nil))

Disable Mouse

(use-package disable-mouse
  :straight t
  :bind (([mouse-4] . (lambda ()
                        (interactive)
                        (scroll-down 1)))
         ([mouse-5] . (lambda ()
                        (interactive)
                        (scroll-up 1)))))

Custom Functions

Reload the init-file

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

(defun radian-eval-buffer ()
  "Evaluate the current buffer as Elisp code."
  (interactive)
  (message "Evaluating %s..." (buffer-name))
  (straight-transaction
    (if (null buffer-file-name)
        (eval-buffer)
      (when (string= buffer-file-name user-init-file)
        (straight-mark-transaction-as-init))
      (load-file buffer-file-name)))
  (message "Evaluating %s... done." (buffer-name)))

Insert Date

(defun nasy:insert-current-date ()
  "Insert current date."
  (interactive)
  (insert (shell-command-to-string "echo -n $(date +'%b %d, %Y')")))

(defun nasy:insert-current-filename ()
  "Insert current buffer filename."
  (interactive)
  (insert (file-relative-name buffer-file-name)))

Rearrange split windows

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

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

(global-set-key (kbd "C-x |") 'split-window-horizontally-instead)
(global-set-key (kbd "C-x _") 'split-window-vertically-instead)

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

(global-set-key (kbd "<f7>") 'nasy:split-window)

Editor

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

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

Default Settings

Default settings for editor.

Diminish

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

Advance Words Count

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

Anzu

(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
  :init
  (define-auto-insert
    '("\\.py" . "Python Language")
    '("Python Language"
      "#!/usr/bin/env python3\n"
      "# -*- coding: utf-8 -*-\n"
      "r\"\"\"\n"
      "Life's pathetic, have fun (\"▔□▔)/hi~♡ Nasy.\n\n"
      "Excited without bugs::\n\n"
      "    |             *         *\n"
      "    |                  .                .\n"
      "    |           .\n"
      "    |     *                      ,\n"
      "    |                   .\n"
      "    |\n"
      "    |                               *\n"
      "    |          |\\___/|\n"
      "    |          )    -(             .              ·\n"
      "    |         =\\ -   /=\n"
      "    |           )===(       *\n"
      "    |          /   - \\\n"
      "    |          |-    |\n"
      "    |         /   -   \\     0.|.0\n"
      "    |  NASY___\\__( (__/_____(\\=/)__+1s____________\n"
      "    |  ______|____) )______|______|______|______|_\n"
      "    |  ___|______( (____|______|______|______|____\n"
      "    |  ______|____\\_|______|______|______|______|_\n"
      "    |  ___|______|______|______|______|______|____\n"
      "    |  ______|______|______|______|______|______|_\n"
      "    |  ___|______|______|______|______|______|____\n\n"
      "author   : Nasy https://nasy.moe\n"
      "date     : " (format-time-string "%b %e, %Y") \n
      "email    : Nasy <nasyxx+python@gmail.com>" \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"
      "\"\"\"\n"))

  (define-auto-insert
    '("\\.hs" . "Haskell Language")
    '("Haskell Language"
      "{-\n"
      " Excited without bugs, have fun (\"▔□▔)/hi~♡ Nasy.\n"
      " ------------------------------------------------\n"
      " |             *         *\n"
      " |                  .                .\n"
      " |           .\n"
      " |     *                      ,\n"
      " |                   .\n"
      " |\n"
      " |                               *\n"
      " |          |\\___/|\n"
      " |          )    -(             .              ·\n"
      " |         =\\ -   /=\n"
      " |           )===(       *\n"
      " |          /   - \\\n"
      " |          |-    |\n"
      " |         /   -   \\     0.|.0\n"
      " |  NASY___\\__( (__/_____(\\=/)__+1s____________\n"
      " |  ______|____) )______|______|______|______|_\n"
      " |  ___|______( (____|______|______|______|____\n"
      " |  ______|____\\_|______|______|______|______|_\n"
      " |  ___|______|______|______|______|______|____\n"
      " |  ______|______|______|______|______|______|_\n"
      " |  ___|______|______|______|______|______|____\n\n"
      "There are more things in heaven and earth, Horatio, than are dreamt.\n"
      "   -- From \"Hamlet\"\n"
      "--------------------------------------------------------------------------------\n\n-}\n\n"
      "--------------------------------------------------------------------------------\n-- |\n"
      "-- Filename   : " (file-name-nondirectory (buffer-file-name)) \n
      "-- Project    : " (file-name-nondirectory (directory-file-name (or projectile-project-root default-directory))) \n
      "-- Author     : Nasy\n"
      "-- License    : GPL-3.0+\n--\n"
      "-- Maintainer : Nasy <nasyxx+haskell@gmail.com>\n"
      "--\n--\n--\n--------------------------------------------------------------------------------\n")))

Beacon

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

Beginend

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

Carbon Now sh

Emacs to carbon.now.sh integration.

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

Try: @@html: <kbd>M-x</kbd> <kbd>carbon-now-sh</kbd> <kbd>RET</kbd> @@

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

Cheat Sh

(straight-use-package 'cheat-sh)

Company

Company

(use-package company
  :straight t
  :init
  (setq-default company-minimum-prefix-length .2
                company-transformers '(company-sort-by-backend-importance)
                company-require-match nil
                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))
  :config
  (defvar my-prev-whitespace-mode nil)
  (make-variable-buffer-local 'my-prev-whitespace-mode)
  (defun pre-popup-draw ()
    "Turn off whitespace mode before showing company complete tooltip"
    (if whitespace-mode
        (progn
          (setq my-prev-whitespace-mode t)
          (whitespace-mode -1)
          (setq my-prev-whitespace-mode t))))
  (defun post-popup-draw ()
    "Restore previous whitespace mode after showing company tooltip"
    (if my-prev-whitespace-mode
        (progn
          (whitespace-mode 1)
          (setq my-prev-whitespace-mode nil))))
  (advice-add 'company-pseudo-tooltip-unhide :before #'pre-popup-draw)
  (advice-add 'company-pseudo-tooltip-hide :after #'post-popup-draw)

  (defun nasy:local-push-company-backend (backend)
    "Add BACKEND to a buffer-local version of `company-backends'."
    (make-local-variable 'company-backends)
    (push backend company-backends))

  (diminish 'company-mode "CMP"))

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))
  :hook ((after-init . company-quickhelp-mode)))

Company Math

(straight-use-package 'company-math)

Company Flx

(use-package company-flx
  :straight t
  :after company
  :hook ((after-init . (lambda () (company-flx-mode +1)))))

Dash

(straight-use-package 'dash)

Dash Functional

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

Dired

Dired

(use-package dired
  :init
  (let ((gls (executable-find "gls")))
    (when gls (setq insert-directory-program gls)))
  (setq dired-recursive-deletes 'top)
  :bind (:map dired-mode-map
              ([mouse-2] . dired-find-file             )
              ("C-c C-p" . wdired-change-to-wdired-mode)))

Diredfl

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

Uniquify

(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

(use-package diff-hl
  :after dired
  :straight t
  :hook ((dired-mode . diff-hl-dired-mode)))

Easy Kill

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

Eldoc

Eldoc Mode

(use-package eldoc
  :hook ((org-mode . eldoc-mode)))

Eldoc Box

(use-package eldoc-box
  :straight (eldoc-box :type git :host github :repo "casouri/eldoc-box")
  :hook ((eldoc-mode . eldoc-box-hover-mode)))

Fill Column

Unfill

(straight-use-package 'unfill)

Visual-fill-column

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

Flycheck

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


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

Grab Mac Link

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

Grep

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

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

Helm

Helm

(use-package helm
   :defer t
   :straight t
   :diminish helm-mode
   :bind (("M-x"       . helm-M-x)
          ("C-o"       . helm-occur)
          ("<f1> SPC"  . helm-all-mark-rings) ; I modified the keybinding
          ("M-y"       . helm-show-kill-ring)
          ("C-x c x"   . helm-register)    ; C-x r SPC and C-x r j
          ("C-x c g"   . helm-google-suggest)
          ("C-x c M-:" . helm-eval-expression-with-eldoc)
          ("C-x C-f"   . helm-find-files)
          ("C-x b"     . nasy:helm)      ; *<major-mode> or /<dir> or !/<dir-not-desired> or @<regexp>
          :map 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
          :map shell-mode-map
          ("C-c C-l" . helm-comint-input-ring) ; in shell mode
          :map minibuffer-local-map
          ("C-c C-l" . helm-minibuffer-history))
   :hook ((after-init . (lambda () (helm-mode 1)))
          (after-init . (lambda () (helm-autoresize-mode 1))))
   :init
   (require 'helm-config)

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

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

   (setq helm-split-window-in-side-p           t ; open helm buffer inside current window, not occupy whole other window
         helm-move-to-line-cycle-in-source     t ; move to end or beginning of source when reaching top or bottom of source.
         helm-ff-search-library-in-sexp        t ; search for library in `require' and `declare-function' sexp.
         helm-scroll-amount                    8 ; scroll 8 lines other window using M-<next>/M-<prior>
         helm-ff-file-name-history-use-recentf t
         helm-echo-input-in-header-line        t)

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

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

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

Helm Org

(use-package helm-org
  :defer t
  :config
  (cl-defun helm-org-headings-in-buffer ()
    (interactive)
    (helm :sources (helm-source-org-headings-for-files
                    (list (projectile-completing-read
                           "File to look at headings from: "
                           (projectile-all-project-files))))
          :candidate-number-limit 99999
          :buffer "*helm org inbuffer*")))

Helm Shell

(use-package helm-eshell
  :after helm
  :bind (:map eshell-mode-map
              ("C-c C-l" . helm-eshell-history)))

Helm Descbings

(use-package helm-descbinds
  :straight t
  :after helm
  :hook ((after-init . helm-descbinds-mode)))

Helm Projectile

(use-package helm-projectile
  :straight t
  :hook ((after-init . helm-projectile-on))
  :init
  (setq projectile-completion-system 'helm))

Helm Ag

(use-package helm-ag
  :straight t
  :init (setq helm-ag-fuzzy-match t
              helm-ag-use-grep-ignore-list t
              helm-ag-use-agignore t))

Helm Dash

(use-package helm-dash
  :straight t
  :init (setq helm-dash-docsets-path "~/.docsets"))

Helm Swoop

(use-package helm-swoop
  :straight t
  :bind (("C-s" . helm-swoop))
  :init (setq helm-swoop-move-to-line-cycle   t
              helm-swoop-use-line-number-face t
              helm-swoop-use-fuzzy-match      t))

Helm Ls Git

(use-package helm-ls-git
  :straight t
  :bind (("C-<f6>"   . helm-ls-git-ls)
         ("C-x g"    . helm-ls-git-ls)
         ("C-x C-d"  . helm-browse-project)))

Highlight

cl-lib-highlight

(use-package cl-lib-highlight
  :after lisp-mode
  :straight t
  :config
  (cl-lib-highlight-initialize))

Color Identifiers Mode

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

hl-line

(use-package hl-line
  :hook ((after-init . global-hl-line-mode)))

Highlight Indent Guides

(use-package highlight-indent-guides
  :straight t
  :hook (((prog-mode text-mode) . highlight-indent-guides-mode)))

Highlight Number

(use-package highlight-numbers
  :straight t
  :hook ((after-init . highlight-numbers-mode)))

Htmlize

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

iBuffer

ibuffer

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

Indent

aggressive indent

(use-package aggressive-indent
  :straight t
  :hook (((emacs-lisp-mode
           lisp-mode
           css-mode) . aggressive-indent-mode)))

iSearch

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

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

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

  :bind (:map isearch-mode-map
              ([remap isearch-delete-char] . isearch-del-char)
              ("C-M-w" . isearch-yank-symbol)
              ([(control return)] . isearch-exit-other-end))
  :config
  (when (fboundp 'isearch-occur)
    ;; to match ivy conventions
    (define-key isearch-mode-map (kbd "C-c C-o") 'isearch-occur)))

Keycast

(use-package keycast
  :straight t
  :init (setq keycast-remove-tail-elements nil))

Large File

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

List Unicode Display

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

mmm-mode

(use-package mmm-auto
  :demand t
  :straight mmm-mode
  :init (setq
         mmm-global-mode              'buffers-with-submode-classes
         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:
         ("C-c m r" . set-rectangular-region-anchor)
         ("C-c m c" . mc/edit-lines)
         ("C-c m e" . mc/edit-ends-of-lines)
         ("C-c m a" . mc/edit-beginnings-of-lines)))

Pangu Spacing

(use-package pangu-spacing
  :straight t
  :init (setq 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)

Parens

I use smartparens with rainbow-delimiters instead of paredit.

(add-hook 'after-init-hook 'show-paren-mode)

Smartparens

(use-package smartparens-config
  :straight smartparens
  :hook ((after-init . show-smartparens-global-mode)
         (after-init . smartparens-global-mode))
  :init (setq sp-hybrid-kill-entire-symbol nil))

Rainbow Delimiters

(use-package rainbow-delimiters
  :straight t
  :hook (((prog-mode text-mode) . rainbow-delimiters-mode)))

PDF Tools

(use-package pdf-tools
  :straight t
  :config
  (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

Pretty Mode

(use-package pretty-mode
  :demand t
  :straight t
  :hook (((prog-mode text-mode) . turn-on-pretty-mode)
         (after-init . global-prettify-symbols-mode)
         (python-mode . (lambda ()
                          (mapc (lambda (pair) (push pair prettify-symbols-alist))
                                '(;; Syntax
                                  ("def" .      #x2131)
                                  ;; ("not" .      #x2757)
                                  ("not" .      #xac)
                                  ("in" .       #x2208)
                                  ("not in" .   #x2209)
                                  ("return" .   #x27fc)
                                  ("yield" .    #x27fb)
                                  ("for" .      #x2200)
                                  ;; Extend Functions
                                  ("any" .      #x2754)
                                  ("all" .      #x2201)
                                  ("dict" .     #x1d507)
                                  ("list" .     #x2112)
                                  ("tuple" .    #x2a02)
                                  ("set" .      #x2126)
                                  ;; Base Types
                                  ("int" .      #x2124)
                                  ("float" .    #x211d)
                                  ("str" .      #x1d54a)
                                  ("True" .     #x1d54b)
                                  ("False" .    #x1d53d)
                                  ;; Extend Types
                                  ("Int" .      #x2124)
                                  ("Float" .    #x211d)
                                  ("String" .   #x1d54a)
                                  ;; Mypy
                                  ("Dict" .     #x1d507)
                                  ("List" .     #x2112)
                                  ("Tuple" .    #x2a02)
                                  ("Set" .      #x2126)
                                  ("Iterable" . #x1d50a)
                                  ("Any" .      #x2754)
                                  ("Union" .    #x22c3)))))
         (haskell-mode . (lambda ()
                          (mapc (lambda (pair) (push pair prettify-symbols-alist))
                                '(;; Syntax
                                  ("not" .      #x2757)
                                  ("in" .       #x2208)
                                  ("elem" .     #x2208)
                                  ("not in" .   #x2209)
                                  ("notElem" .  #x2209)
                                  ;; Types
                                  ("String" .   #x1d54a)
                                  ("Int" .      #x2124)
                                  ("Float" .    #x211d)
                                  ("True" .     #x1d54b)
                                  ("False" .    #x1d53d))))))
  :config
  (pretty-activate-groups
   '(:sub-and-superscripts :greek :arithmetic))

  (pretty-deactivate-groups
   '(:equality :ordering :ordering-double :ordering-triple
               :arrows :arrows-twoheaded :punctuation
               :logic :sets :arithmetic-double :arithmetic-triple)))

ipretty

(use-package ipretty
  :defer t
  :straight t
  :hook ((after-init . ipretty-mode)))

Pretty Font

;; https://github.com/tonsky/FiraCode/wiki/Emacs-instructions
;; This works when using emacs --daemon + emacsclient
(add-hook 'after-make-frame-functions (lambda (frame) (set-fontset-font t '(#Xe100 . #Xe16f) "Fira Code Symbol")))
;; This works when using emacs without server/client
(set-fontset-font t '(#Xe100 . #Xe16f) "Fira Code Symbol")
;; I haven't found one statement that makes both of the above situations work, so I use both for now

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

(pretty-fonts-set-kwds
 '((pretty-fonts-fira-font prog-mode-hook org-mode-hook)))

Projectile

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

Recentf

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

Smex

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

Subword

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

Treemacs

(use-package treemacs
  :defer t
  :straight t
  :init
  (with-eval-after-load 'winum
    (define-key winum-keymap (kbd "M-0") #'treemacs-select-window))
  :config
  (progn
    (setq treemacs-collapse-dirs              (if (executable-find "python3") 3 0)
          treemacs-deferred-git-apply-delay   0.5
          treemacs-display-in-side-window     t
          treemacs-file-event-delay           5000
          treemacs-file-follow-delay          0.2
          treemacs-follow-after-init          t
          treemacs-follow-recenter-distance   0.1
          treemacs-goto-tag-strategy          'refetch-index
          treemacs-indentation                2
          treemacs-indentation-string         " "
          treemacs-is-never-other-window      nil
          treemacs-no-png-images              nil
          treemacs-project-follow-cleanup     nil
          treemacs-persist-file               (no-littering-expand-var-file-name "treemacs-persist")
          treemacs-recenter-after-file-follow nil
          treemacs-recenter-after-tag-follow  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 'extended))
      (`(t . _)
       (treemacs-git-mode 'simple))))
  :bind
  (:map global-map
        ("M-0"       . treemacs-select-window)
        ("C-x t 1"   . treemacs-delete-other-windows)
        ("C-x t t"   . treemacs)
        ("C-x t B"   . treemacs-bookmark)
        ("C-x t C-t" . treemacs-find-file)
        ("C-x t M-t" . treemacs-find-tag)))


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

Version Control

Useful Simple Packages

(dolist (package '(git-blamed
                   gitignore-mode
                   gitconfig-mode
                   git-timemachine))
  (straight-use-package package))

Magit

(use-package magit
  :straight t
  :hook ((magit-popup-mode-hook . no-trailing-whitespace))
  :init (setq-default 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
            (magit-todos-mode))
  (when *is-a-mac* (add-hook 'magit-mode-hook (lambda () (local-unset-key [(meta h)])))))

(straight-use-package 'magit-todos)

Magit Org Todos

(use-package magit-org-todos
  :after    org
  :straight t
  :config   (magit-org-todos-autoinsert))

Forge

(use-package forge
  :straight (forge :type git :host github :repo "magit/forge"))

Git Commit

(use-package git-commit
  :straight t
  :hook ((git-commit-mode . goto-address-mode)))

Git Messenger

(use-package git-messenger
  :straight t
  :init (setq git-messenger:show-detail t)
  :bind (:map vc-prefix-map
         ("p" . git-messenger:popup-message)))

Git Gutter

(use-package git-gutter
  :straight t
  :diminish
  :hook (after-init . global-git-gutter-mode)
  :bind (("C-x v =" . git-gutter:popup-hunk)
         ("C-x p"   . git-gutter:previous-hunk)
         ("C-x n"   . git-gutter:next-hunk))
  :init (setq 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 ""))

Github Gist

(use-package gist
  :straight t)

Which Function

(use-package which-func
  :demand t
  :hook ((after-init . which-function-mode)))

Which Key

(use-package which-key
  :straight t
  :hook ((after-init . which-key-mode)))

Whitespace

(use-package whitespace
  :preface
  (defun no-trailing-whitespace ()
    "Turn off display of trailing whitespace in this buffer."
    (setq show-trailing-whitespace nil))
  :init
  (setq-default show-trailing-whitespace t
                whitespace-style         '(face tabs empty trailing lines-tail))

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


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

Yasnippet

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

(use-package yasnippet-snippets :straight t)

Languages

Simple Supported Languages

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

Language Server Protocol

lsp-mode

(use-package lsp
  :straight lsp-mode
  :hook ((lsp-after-open . lsp-enable-imenu))
  :init (setq lsp-prefer-flymake  nil)
  :config (require 'lsp-clients))

lsp-ui

(use-package lsp-ui
  :demand t
  :after lsp-mode
  :straight t
  :bind (:map lsp-ui-mode-map
              ([remap xref-find-definitions] . lsp-ui-peek-find-definitions)
              ([remap xref-find-references]  . lsp-ui-peek-find-references)
              ("C-c u" . lsp-ui-imenu))
  :hook ((lsp-mode . lsp-ui-mode))
  :init
  (setq-default lsp-ui-doc-position 'at-point
                lsp-ui-doc-header nil
                ;; lsp-ui-doc-include-signature nil
                lsp-ui-sideline-update-mode 'point
                lsp-ui-sideline-delay 1
                lsp-ui-sideline-ignore-duplicate t
                lsp-ui-peek-always-show t))

company-lsp

(use-package company-lsp
  :defer t
  :after lsp-mode
  :straight t
  :init
  (setq company-lsp-async               t
        company-lsp-enable-recompletion t
        company-lsp-enable-snippet      t
        company-lsp-cache-candidates    nil))

Debug Adapter Protocol

Dap Mode

(use-package dap-mode
  :straight t
  :config
  (require 'dap-python))

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

I use clangd

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

Haskell

Include haskell-mode, lsp-haskell and intero.

Haskell-Mode

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

  :hook ((haskell-mode . subword-mode)
         (haskell-mode . haskell-auto-insert-module-template)
         (haskell-mode . haskell-collapse-mode)
         (haskell-mode . stack-exec-path-mode)
         (haskell-mode . (lambda () (setq-local tab-width 4))))
  :bind (("C-x a a" . align)
         :map haskell-mode-map
         ("C-c h" . hoogle)
         ("C-o"   . open-line))
  :init
  (setq haskell-mode-stylish-haskell-path            "stylish-haskell"
        haskell-indentation-layout-offset            4
        haskell-process-suggest-haskell-docs-imports 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)

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

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

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

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

  If optional AND-THEN-FIND-THIS-TAG argument is present it is used
  with function `xref-find-definitions' after new table was
  generated."
    (interactive)
    (let* ((dir (haskell-cabal--find-tags-dir))
           (command (haskell-cabal--compose-hasktags-command dir)))
      (if (not command)
          (error "Unable to compose hasktags command")
        ;; I disabled the noisy shell command output.
        ;; The original is (shell-command command)
        (call-process-shell-command command nil "*Shell Command Output*" t)
        (haskell-mode-message-line "Tags generated.")
        (when and-then-find-this-tag
          (let ((tags-file-name dir))
            (xref-find-definitions and-then-find-this-tag)))))))

LSP Haskell

(use-package lsp-haskell
  :straight t
  :hook ((haskell-mode   . lsp)
         (lsp-after-open . (lambda () (add-hook 'before-save-hook #'lsp-format-buffer nil t))))
  ;; You can set the lsp-haskell settings here
  ;; (lsp-haskell-set-hlint-on)                    ;; default on
  ;; (lsp-haskell-set-max-number-of-problems 100)  ;; default 100
  ;; (lsp-haskell-set-liquid-on)                   ;; default off
  ;; (lsp-haskell-set-completion-snippets-on)      ;; default on
  )

intero

(when *intero*
  (use-package intero
    :straight t
    :after haskell-mode
    :hook (haskell-mode . (lambda () (intero-global-mode 1)))
    :config (define-key intero-mode-map (kbd "M-?") nil)))

Structured Haskell Mode

(if (and *struct-hs* *struct-hs-path*)
    (progn
      (add-to-list 'load-path *struct-hs-path*)
      (require 'shm)
      (setq shm-program-name *struct-hs*)
      (add-hook #'haskell-mode-hook #'structured-haskell-mode))
  (progn
    (when *struct-hs*
      (message (concat "*NOTE* about structured-haskell-mode:\n"
                       "https://github.com/projectional-haskell/structured-haskell-mode\n"
                       "No structured-haskell-mode elisp find.\n"
                       "If you want to use it, \n"
                       "please install it and config its variables *struct-hs-path* in user-config.el\n")))))

Lisp

lisp-mode

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

Highlight-quoted

(use-package highlight-quoted
  :defer t
  :straight t
  :hook ((emacs-lisp-mode . highlight-quoted-mode)))

elisp-def

(use-package elisp-def
  :straight t
  :hook (((emacs-lisp-mode ielm-mode) . elisp-def-mode)))

Markdown

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

Python

Include python-mode, blacken, py-isort and flycheck-prospector.

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

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

  (defvar lsp-python--config-options (make-hash-table))

  (defun lsp-python--set-configuration ()
    (lsp--set-configuration `(:pyls ,lsp-python--config-options)))

  (add-hook 'lsp-after-initialize-hook 'lsp-python--set-configuration)

  (defun lsp-python-set-config (name option)
    "Set a config option in the python lsp server."
    (puthash name option lsp-python--config-options))

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

  (defun lsp-python-config-set ()
    "Set python lsp config."
    (lsp-python-set-config "configurationSources"          '("pycodestyle" "pyflakes" "pydocstyle"))
    (lsp-python-set-config "plugins.pydocstyle.enabled"    t)
    (lsp-python-set-config "plugins.pydocstyle.convention" "pep257")
    (lsp-python-set-config "plugins.yapf.enabled"          nil)

    (lsp-python-set-config "plugins.jedi_definition.follow_imports"         t)
    (lsp-python-set-config "plugins.jedi_definition.follow_builtin_imports" t)

    (lsp-python-set-config "plugins.pyls_mypy.live_mode" nil)  ;; nothing happened. So I use a fork that disable it default.
    (lsp-python--set-configuration))

  :hook ((python-mode . lsp)
         (python-mode . lsp-python-config-set)
         (python-mode . (lambda () (nasy:local-push-company-backend '(company-dabbrev-code
                                                                 company-gtags
                                                                 company-etags
                                                                 company-keywords))))
         (python-mode . setq-after)
         (python-mode . (lambda () (nasy:local-push-company-backend 'company-lsp))))
  :init (setq-default 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 --simple-prompt --classic"
                      py-ipython-command-args               "-i --simple-prompt --classic"
                      py-python-command                     "python3"
                      flycheck-python-pycompile-executable "python3"
                      flycheck-python-pylint-executable    "python3"
                      python-mode-modeline-display         "Python"
                      python-skeleton-autoinsert           t)
  :config
  (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))

(use-package flycheck-prospector
  :disabled t
  :straight (flycheck-prospector :type git :host github :repo "nasyxx/flycheck-prospector")
  :init (setq flycheck-prospector-profile-path "~/.config/prospector/prospector.yaml")
  :hook ((flycheck-mode . flycheck-prospector-setup))
  :config
  (add-to-list 'flycheck-disabled-checkers 'python-flake8)
  (add-to-list 'flycheck-disabled-checkers 'python-pylint))

Rust

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

Load

I use org with org-plus-contrib

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

OX Org

Other ox-_ packages.

(straight-use-package 'ox-rst)

(require 'ox-md)

Basic Configs

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

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

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

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

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

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

  :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))
  :init
  (setq
   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-export-backends                           '(ascii html latex md)
   org-export-coding-system                      'utf-8
   org-export-kill-product-buffer-when-displayed t
   org-export-with-sub-superscripts              '{}
   org-use-sub-superscripts                      '{}

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

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

   org-html-checkbox-type       'html
   org-html-doctype             "html5"
   org-html-html5-fancy         t
   org-html-htmlize-output-type '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 latex
   org-latex-compiler "lualatex"
   org-latex-default-packages-alist
   (quote
    (("AUTO" "inputenc" t
      ("pdflatex"))
     ("T1" "fontenc" t
      ("pdflatex"))
     ("" "graphicx" t nil)
     ("" "grffile" t nil)
     ("" "longtable" t nil)
     ("" "wrapfig" nil nil)
     ("" "rotating" nil nil)
     ("normalem" "ulem" t nil)
     ("" "amsmath" t nil)
     ("" "textcomp" t nil)
     ("" "amssymb" t nil)
     ("" "capt-of" nil nil)
     ("colorlinks,linkcolor=blue,anchorcolor=blue,citecolor=green,filecolor=black,urlcolor=blue"
      "hyperref" t nil)
     ("" "luatexja-fontspec" t nil)
     ("" "listings" t nil)))
   org-latex-default-table-environment "longtable"
   org-latex-listings t
   org-latex-listings-langs
   (quote
    ((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")))
   org-latex-pdf-process
   (quote
    ("lualatex -shell-escape -interaction nonstopmode %f"
     "lualatex -shell-escape -interaction nonstopmode %f"))
   org-latex-tables-booktabs t

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

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

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

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

   org-src-lang-modes '(("C"         . c)
                        ("C++"       . c++)
                        ("asymptote" . asy)
                        ("bash"      . sh)
                        ("beamer"    . latex)
                        ("calc"      . fundamental)
                        ("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(c@/!)")
                                    (sequence "WAITING(w@/!)" "DELEGATED(e!)" "HOLD(h)" "|" "CANCELLED(c@/!)")))
   org-todo-repeat-to-state "NEXT"
   org-todo-keyword-faces   (quote (("NEXT" :inherit warning)
                                    ("PROJECT" :inherit font-lock-string-face))))
  :config
  ;; --------
  (org-babel-do-load-languages
   'org-babel-load-languages
   `((ditaa      . t)
     (dot        . t)
     (elvish     . t)
     (emacs-lisp . t)
     (gnuplot    . t)
     (haskell    . nil)
     (latex      . t)
     (ledger     . t)
     (ocaml      . nil)
     (octave     . t)
     (plantuml   . t)
     (python     . t)
     (R          . t)
     (ruby       . t)
     (screen     . nil)
     (,(if (locate-library "ob-sh") 'sh 'shell) . t)
     (sql . nil)
     (sqlite . t)))

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

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

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

Org-Agenda

(use-package org-agenda
  :init (setq-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"))

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

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

Org Bullets

(use-package org-bullets
  :straight t
  :hook ((org-mode . (lambda () (org-bullets-mode 1)))))

Org Capture

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

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

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

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

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

Org Cliplink

(straight-use-package 'org-cliplink)

Org Clock

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

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

Org Extra Jar – ob-ditaa & ob-plantuml

Include ob-ditaa and ob-plantuml

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

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

Org Pdfview

(straight-use-package 'org-pdfview)

Org Pomodoro

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

Org Toc

(straight-use-package 'toc-org)

Org Wc

(straight-use-package 'org-wc)

Themes

Main Theme

I use doom-themes.

(use-package doom-themes
  :demand   t
  :straight t
  :config
  (load-theme nasy:theme t)
  (doom-themes-treemacs-config)  ;; The doom themes havn't finished it yet.
  (doom-themes-visual-bell-config)
  (doom-themes-org-config))

Font

(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
  :demand t
  :init (setq inhibit-compacting-font-caches t)
  :straight t)

Mode Line

(use-package nyan-mode
  :demand t
  :straight t
  :init (setq nyan-animate-nyancat t
              nyan-bar-length 16
              nyan-wavy-trail t)
  :config (nyan-mode 1))


(use-package spaceline-config
  :init
  (setq-default
   mode-line-format '("%e" (:eval (spaceline-ml-main)))
   powerline-default-separator 'contour
   powerline-gui-use-vcs-glyph t
   powerline-height 22
   spaceline-highlight-face-func 'spaceline-highlight-face-modified
   spaceline-workspace-numbers-unicode t
   spaceline-window-numbers-unicode t
   spaceline-separator-dir-left '(left . right)
   spaceline-separator-dir-right '(right . left)
   spaceline-flycheck-bullet "❀ %s")
  (spaceline-helm-mode 1)
  (spaceline-info-mode 1)
  :straight spaceline
  :config
  (spaceline-define-segment nasy:version-control
    "Version control information."
    (when vc-mode
      (let ((branch (mapconcat 'concat (cdr (split-string vc-mode "[:-]")) "-")))
        (powerline-raw
         (s-trim (concat ""
                         branch
                         (when (buffer-file-name)
                           (pcase (vc-state (buffer-file-name))
                             (`up-to-date "")
                             (`edited "")
                             (`added "")
                             (`unregistered "")
                             (`removed "")
                             (`needs-merge "")
                             (`needs-update "")
                             (`ignored "")
                             (_ "")))))))))

  (spaceline-define-segment nasy-time
    "Time"
    (format-time-string "%b %d, %Y - %H:%M ")
    :tight-right t)

  (spaceline-define-segment flycheck-status
    "An `all-the-icons' representaiton of `flycheck-status'"
    (let* ((text
            (pcase flycheck-last-status-change
              (`finished (if flycheck-current-errors
                             (let ((count (let-alist (flycheck-count-errors flycheck-current-errors)
                                            (+ (or .warning 0) (or .error 0)))))
                               (format "%s Issue%s" count (if (eq 1 count) "" "s")))
                           "✔ No Issues"))
              (`running     "⟲ Running")
              (`no-checker  "")
              (`not-checked "✣ Disabled")
              (`errored     "⚠ Error")
              (`interrupted "⛔ Interrupted")
              (`suspicious  "")))
           (f (cond
               ((string-match "" text) `(:height 0.9 :foreground ,(face-attribute 'spaceline-flycheck-warning :foreground)
                                                  :background "#1d5464"))
               ((string-match "✖ [0-9]" text) `(:height 0.9 :background ,(face-attribute 'spaceline-flycheck-error :foreground)
                                                        :foreground "#333333"))
               ((string-match "✣ Disabled" text) `(:height 0.9))
               (t '(:height 0.9 :inherit)))))
      (propertize (format " %s " text)
                  'face f
                  'help-echo "Show Flycheck Errors"
                  'mouse-face '(:box 1)
                  'local-map (make-mode-line-mouse-map 'mouse-1 (lambda () (interactive) (flycheck-list-errors)))))
    :when active)

  (set-face-attribute 'keycast-key t :weight 'bold :height 1 :background "#cdeeaa" :foreground "#36622b" :box nil)

  (spaceline-define-segment nasy:keycast-keys
    "Keycast modeline segment."
    (and (funcall keycast-window-predicate)
         (let* ((key (ignore-errors
                       (key-description keycast--this-command-keys)))
                (cmd keycast--this-command)
                (elt (or (assoc cmd keycast-substitute-alist)
                         (assoc key keycast-substitute-alist))))
           (when elt
             (pcase-let ((`(,_ ,k ,c) elt))
               (unless (eq k t) (setq key k))
               (unless (eq c t) (setq cmd c))))
           (and key cmd
                (concat
                 (propertize (let ((pad (max 2 (- 5 (length key)))))
                               (concat (make-string (ceiling pad 2) ?\s) key
                                       (make-string (floor   pad 2) ?\s)))
                             'face 'keycast-key)
                 ;; (format " %s" (propertize (symbol-name cmd)
                 ;;                           'face 'keycast-command))
                 )))))

  (add-hook
   'after-init-hook
   (lambda () (spaceline-compile
           `(((buffer-modified major-mode buffer-size) :face highlight-face)
             (anzu)
             (auto-compile)
             ((nasy:version-control project-name) :separator " in " :face 'spaceline-flycheck-warning :when active)
             ((nasy:version-control project-name) :separator " in " :when (not active))
             (buffer-id)
             (selection-info)
             (nyan-cat :tight t))
           `((line-column :when active)
             (line-column :when (not active))
             (global :when active)
             (process)
             ;; (minor-modes)
             (buffer-position
              hud)
             (nasy:keycast-keys)
             ((flycheck-status (flycheck-error flycheck-warning flycheck-info)) :when active)
             (nasy-time :face 'spaceline-evil-replace :when active)
             (nasy-time :when (not active)))))))

Epilogue

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

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

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

;;; init.el ends here

About

My emacs configuration


Languages

Language:Emacs Lisp 77.7%Language:Makefile 22.3%