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.

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

NOTICE

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

Screenshots

screenshot1.png
screenshot2.png
screenshot3.png

Dependencies

  • Emacs
  • git
  • make

Installation

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

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

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

You can regenerate init.el by make generate.

Updates

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

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

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

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

Custom Configuration

Example Custom Configuration

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

(setq-default
 ;;calendar-latitude        24.8801
 ;;calendar-longitude       102.8329
 ;;user-mail-address        "[email protected]"
 ;;initial-buffer-choice    #'(lambda () (get-buffer "*dashboard*"))
 ;;diary-file               ~/dairy/emacs-dairy
 gcmh-high-cons-threshold #x40000000
 *theme*                  'nasy
 *debug*                  t
 *struct-hs*              nil
 ;;*vterm*                  t
 *risky-var*              nil
 *dvorak*                 nil
 *dvorak-trans*           nil
 *font-cjk*               "Kaiti SC"
 *font-weight-cjk*        'normal)
(provide 'user-config-example)

dashboard

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

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

in your custom/user-config.el.

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

NOTICE:

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

Features

Summary

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

The Configuration

See the complete literate config here:

Html

Source

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

File Header

This includes some necessary headers.

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

;; Author: Nasy <[email protected]>

;;; Commentary:

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

Lexical Binding

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

(setq-default lexical-binding t)

Bootstrap

In this section, it will include default settings, load-path and packages manager. At the same time, it will initialize the benchmark and garbage collection.

;;------------------------------------------------------------------------------
;; Bootstrap
(add-to-list 'load-path (expand-file-name "config" user-emacs-directory))
(require 'nasy-bootstrap)

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
              gc-cons-threshold      most-positive-fixnum)

If this os is macOS?

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

Packages Manager

I use straight.el as my packages manager.

At the same time, I use leaf.el to manage packages' loading.

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

(defvar bootstrap-version)

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

(defmacro nasy/s-u-p (&rest packages)
  "Straight use multiple PACKAGES.

Usage:

    \(nasy/s-u-p nil t 'avy avx *eldoc-use* (avy :type git)
                 (:when nil ax3) (:when t 'axx ax2) (:when t axy 'axy2))

to

    \(progn
       (straight-use-package 'avy)
       (straight-use-package 'avx)
       (if *eldoc-use*
           (progn
             (straight-use-package *eldoc-use*)))
       (straight-use-package
        '(avy :type git))
       nil
       (progn
         (straight-use-package 'axx)
         (straight-use-package 'ax2))
       (progn
         (straight-use-package 'axy)
         (straight-use-package 'axy2)))"
  (declare (indent defun))
  `(progn
     ,@(cl-loop for package in packages
                when (and package
                         (not (eq package t)))
                collect
                (cond ((and (symbolp package)
                           (or (not (boundp package))
                              (fboundp package)))
                       `(straight-use-package ',package))
                      ((symbolp package)
                       `(when ,package
                          (straight-use-package ,package)))
                      ((consp package)
                       (let ((fst (car package))
                             (rst (cdr package)))
                         (cond ((eq :when fst)
                                `(when ,(car rst)
                                   (nasy/s-u-p ,@(cdr rst))))
                               ((eq 'quote fst)
                                `(straight-use-package ,package))
                               (t `(straight-use-package ',package)))))
                      (t nil)))))


(nasy/s-u-p leaf leaf-keywords)
(leaf-keywords-init)

;; Feature `straight-x' from package `straight' provides
;; experimental/unstable extensions to straight.el which are not yet
;; ready for official inclusion.
(leaf straight-x
  ;; Add an autoload for this extremely useful command.
  :commands (straight-x-fetch-all))

Load Path

Literate config will generate emacslisp files to config folder. However, we use straight.el to handle them, we do not need to add them to load-path manually.

(defmacro nasy/local-repo (repo)
  "Nasy load local REPO."
  (let ((n-repo (format "nasy-%s" (symbol-name repo))))
    `(progn
       (straight-use-package
        '(,(intern n-repo)
          :local-repo ,(expand-file-name
                        (format "config/%s" (symbol-name repo))
                        user-emacs-directory))))))

Also, there is a custom directory.

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

Benchmark-init

This is a simple benchmark of calls to Emacs require and load functions. It can be used to keep track of where time is being spent during Emacs startup in order to optimize startup times.

https://github.com/dholm/benchmark-init-el

(straight-use-package 'benchmark-init)
(leaf benchmark-init
  :doc "This is a simple benchmark of calls to Emacs require and load functions."
  :url "https://github.com/dholm/benchmark-init-el"
  :hook ((after-init . benchmark-init/deactivate))
  :init (benchmark-init/activate))

Garbage Collection

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

https://gitlab.com/koral/gcmh

(straight-use-package 'gcmh)
(leaf gcmh
  :doc "Use GCMH --  the Garbage Collector Magic Hack -- to adjust garbage collection."
  :url "https://gitlab.com/koral/gcmh"
  :custom
  (gcmh-verbose             . t)
  (gcmh-lows-cons-threshold . #x800000)
  (gcmh-high-cons-threshold . most-positive-fixnum)
  (gcmh-idle-delay          . 3600)
  :config
  (gcmh-mode))

No Littering

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

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

Load Org

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

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

Core

(nasy/local-repo core)
(require 'nasy-core)

Core Packages

(nasy/s-u-p async default-text-scale diminish general session transient)

Core Libs

Core Libs include useful functions, macros and alias.

Functions
Normal
;;;###autoload
(defun nasy-unquote (exp)
  "Return EXP unquoted."
  (declare (pure t) (side-effect-free t))
  (while (memq (car-safe exp) '(quote function))
    (setq exp (cadr exp)))
  exp)

;;;###autoload
(defun nasy-enlist (exp)
 "Return EXP wrapped in a list, or as-is if already a list."
 (declare (pure t) (side-effect-free t))
 (if (listp exp) exp (list exp)))
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
;;;###autoload
(defun nasy/insert-current-date ()
  "Insert current date."
  (interactive)
  (insert (shell-command-to-string "echo -n $(date +'%b %d, %Y')")))

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

Useful Macros and Alias.

;;;###autoload
(if (fboundp 'with-eval-after-load)
    (defalias 'after-x 'with-eval-after-load)
  (defmacro after-x (feature &rest body)
    "Eval BODY afetr FEATURE have loaded."
    (declare (indent defun))
    `(eval-after-load ,feature
       '(progn ,@body))))

Core Buffer

Buffers Define and Autoloads.

Functions
;;;###autoload
(defvar nasy/real-buffer-functions
  '(nasy/dired-buffer-p)
  "A list of predicate functions run to determine if a buffer is real, unlike
`nasy/unreal-buffer-functions'. They are passed one argument: the buffer to be
tested.
Should any of its function returns non-nil, the rest of the functions are
ignored and the buffer is considered real.
See `nasy/real-buffer-p' for more information.")

;;;###autoload
(defvar nasy/unreal-buffer-functions
  '(minibufferp nasy/special-buffer-p nasy/non-file-visiting-buffer-p)
  "A list of predicate functions run to determine if a buffer is *not* real,
unlike `nasy/real-buffer-functions'. They are passed one argument: the buffer to
be tested.
Should any of these functions return non-nil, the rest of the functions are
ignored and the buffer is considered unreal.
See `nasy/real-buffer-p' for more information.")

;;;###autoload
(defvar-local nasy/real-buffer-p nil
  "If non-nil, this buffer should be considered real no matter what. See
`nasy/real-buffer-p' for more information.")

;;;###autoload
(defvar nasy/fallback-buffer-name "*scratch*"
  "The name of the buffer to fall back to if no other buffers exist (will create
it if it doesn't exist).")


;;
;; Functions

;;;###autoload
(defun nasy/buffer-frame-predicate (buf)
  "To be used as the default frame buffer-predicate parameter. Returns nil if
BUF should be skipped over by functions like `next-buffer' and `other-buffer'."
  (or (nasy/real-buffer-p buf)
      (eq buf (nasy/fallback-buffer))))

;;;###autoload
(defun nasy/fallback-buffer ()
  "Returns the fallback buffer, creating it if necessary. By default this is the
scratch buffer. See `nasy/fallback-buffer-name' to change this."
  (let (buffer-list-update-hook)
    (get-buffer-create nasy/fallback-buffer-name)))

;;;###autoload
(defalias 'nasy/buffer-list #'buffer-list)

;;;###autoload
(defun nasy/project-buffer-list (&optional project)
  "Return a list of buffers belonging to the specified PROJECT.
If PROJECT is nil, default to the current project.
If no project is active, return all buffers."
  (let ((buffers (nasy/buffer-list)))
    (if-let* ((project-root
               (if project (expand-file-name project)
                 (nasy/project-root))))
        (cl-loop for buf in buffers
                 if (projectile-project-buffer-p buf project-root)
                 collect buf)
      buffers)))

;;;###autoload
(defun nasy/open-projects ()
  "Return a list of projects with open buffers."
  (cl-loop with projects = (make-hash-table :test 'equal :size 8)
           for buffer in (nasy/buffer-list)
           if (buffer-live-p buffer)
           if (nasy/real-buffer-p buffer)
           if (with-current-buffer buffer (nasy/project-root))
           do (puthash (abbreviate-file-name it) t projects)
           finally return (hash-table-keys projects)))

;;;###autoload
(defun nasy/dired-buffer-p (buf)
  "Returns non-nil if BUF is a dired buffer."
  (with-current-buffer buf (derived-mode-p 'dired-mode)))

;;;###autoload
(defun nasy/special-buffer-p (buf)
  "Returns non-nil if BUF's name starts and ends with an *."
  (equal (substring (buffer-name buf) 0 1) "*"))

;;;###autoload
(defun nasy/temp-buffer-p (buf)
  "Returns non-nil if BUF is temporary."
  (equal (substring (buffer-name buf) 0 1) " "))

;;;###autoload
(defun nasy/visible-buffer-p (buf)
  "Return non-nil if BUF is visible."
  (get-buffer-window buf))

;;;###autoload
(defun nasy/buried-buffer-p (buf)
  "Return non-nil if BUF is not visible."
  (not (nasy/visible-buffer-p buf)))

;;;###autoload
(defun nasy/non-file-visiting-buffer-p (buf)
  "Returns non-nil if BUF does not have a value for `buffer-file-name'."
  (not (buffer-file-name buf)))

;;;###autoload
(defun nasy/real-buffer-list (&optional buffer-list)
  "Return a list of buffers that satify `nasy/real-buffer-p'."
  (cl-remove-if-not #'nasy/real-buffer-p (or buffer-list (nasy/buffer-list))))

;;;###autoload
(defun nasy/real-buffer-p (buffer-or-name)
  "Returns t if BUFFER-OR-NAME is a 'real' buffer.
A real buffer is a useful buffer; a first class citizen in Doom. Real ones
should get special treatment, because we will be spending most of our time in
them. Unreal ones should be low-profile and easy to cast aside, so we can focus
on real ones.
The exact criteria for a real buffer is:
  1. A non-nil value for the buffer-local value of the `nasy/real-buffer-p'
     variable OR
  2. Any function in `nasy/real-buffer-functions' returns non-nil OR
  3. None of the functions in `nasy/unreal-buffer-functions' must return
     non-nil.
If BUFFER-OR-NAME is omitted or nil, the current buffer is tested."
  (or (bufferp buffer-or-name)
      (stringp buffer-or-name)
      (signal 'wrong-type-argument (list '(bufferp stringp) buffer-or-name)))
  (when-let (buf (get-buffer buffer-or-name))
    (and (buffer-live-p buf)
         (not (nasy/temp-buffer-p buf))
         (or (buffer-local-value 'nasy/real-buffer-p buf)
             (run-hook-with-args-until-success 'nasy/real-buffer-functions buf)
             (not (run-hook-with-args-until-success 'nasy/unreal-buffer-functions buf))))))

;;;###autoload
(defun nasy/unreal-buffer-p (buffer-or-name)
  "Return t if BUFFER-OR-NAME is an 'unreal' buffer.
See `nasy/real-buffer-p' for details on what that means."
  (not (nasy/real-buffer-p buffer-or-name)))

;;;###autoload
(defun nasy/buffers-in-mode (modes &optional buffer-list derived-p)
  "Return a list of buffers whose `major-mode' is `eq' to MODE(S).
If DERIVED-P, test with `derived-mode-p', otherwise use `eq'."
  (let ((modes (nasy/enlist modes)))
    (cl-remove-if-not (if derived-p
                          (lambda (buf)
                            (with-current-buffer buf
                              (apply #'derived-mode-p modes)))
                        (lambda (buf)
                          (memq (buffer-local-value 'major-mode buf) modes)))
                      (or buffer-list (nasy/buffer-list)))))

;;;###autoload
(defun nasy/visible-windows (&optional window-list)
  "Return a list of the visible, non-popup (dedicated) windows."
  (cl-loop for window in (or window-list (window-list))
           when (or (window-parameter window 'visible)
                    (not (window-dedicated-p window)))
           collect window))

;;;###autoload
(defun nasy/visible-buffers (&optional buffer-list)
  "Return a list of visible buffers (i.e. not buried)."
  (if buffer-list
      (cl-remove-if-not #'get-buffer-window buffer-list)
    (delete-dups (mapcar #'window-buffer (window-list)))))

;;;###autoload
(defun nasy/buried-buffers (&optional buffer-list)
  "Get a list of buffers that are buried."
  (cl-remove-if #'get-buffer-window (or buffer-list (nasy/buffer-list))))

;;;###autoload
(defun nasy/matching-buffers (pattern &optional buffer-list)
  "Get a list of all buffers that match the regex PATTERN."
  (cl-loop for buf in (or buffer-list (nasy/buffer-list))
           when (string-match-p pattern (buffer-name buf))
           collect buf))

;;;###autoload
(defun nasy/set-buffer-real (buffer flag)
  "Forcibly mark BUFFER as FLAG (non-nil = real)."
  (with-current-buffer buffer
    (setq nasy/real-buffer-p flag)))

;;;###autoload
(defun nasy/kill-buffer-and-windows (buffer)
  "Kill the buffer and delete all the windows it's displayed in."
  (dolist (window (get-buffer-window-list buffer))
    (unless (one-window-p t)
      (delete-window window)))
  (kill-buffer buffer))

;;;###autoload
(defun nasy/fixup-windows (windows)
  "Ensure that each of WINDOWS is showing a real buffer or the fallback buffer."
  (dolist (window windows)
    (with-selected-window window
      (when (nasy/unreal-buffer-p (window-buffer))
        (previous-buffer)
        (when (nasy/unreal-buffer-p (window-buffer))
          (switch-to-buffer (nasy/fallback-buffer)))))))

;;;###autoload
(defun nasy/kill-buffer-fixup-windows (buffer)
  "Kill the BUFFER and ensure all the windows it was displayed in have switched
to a real buffer or the fallback buffer."
  (let ((windows (get-buffer-window-list buffer)))
    (kill-buffer buffer)
    (nasy/fixup-windows (cl-remove-if-not #'window-live-p windows))))

;;;###autoload
(defun nasy/kill-buffers-fixup-windows (buffers)
  "Kill the BUFFERS and ensure all the windows they were displayed in have
switched to a real buffer or the fallback buffer."
  (let ((seen-windows (make-hash-table :test 'eq :size 8)))
    (dolist (buffer buffers)
      (let ((windows (get-buffer-window-list buffer)))
        (kill-buffer buffer)
        (dolist (window (cl-remove-if-not #'window-live-p windows))
          (puthash window t seen-windows))))
    (nasy/fixup-windows (hash-table-keys seen-windows))))

;;;###autoload
(defun nasy/kill-matching-buffers (pattern &optional buffer-list)
  "Kill all buffers (in current workspace OR in BUFFER-LIST) that match the
regex PATTERN. Returns the number of killed buffers."
  (let ((buffers (nasy/matching-buffers pattern buffer-list)))
    (dolist (buf buffers (length buffers))
      (kill-buffer buf))))


;;
;; Hooks

;;;###autoload
(defun nasy/mark-buffer-as-real-h ()
  "Hook function that marks the current buffer as real."
  (nasy/set-buffer-real (current-buffer) t))


;;
;; Interactive commands

;;;###autoload
(defun nasy/kill-this-buffer-in-all-windows (buffer &optional dont-save)
  "Kill BUFFER globally and ensure all windows previously showing this buffer
have switched to a real buffer or the fallback buffer.
If DONT-SAVE, don't prompt to save modified buffers (discarding their changes)."
  (interactive
   (list (current-buffer) current-prefix-arg))
  (cl-assert (bufferp buffer) t)
  (when (and (buffer-modified-p buffer) dont-save)
    (with-current-buffer buffer
      (set-buffer-modified-p nil)))
  (nasy/kill-buffer-fixup-windows buffer))


(defun nasy/message-or-count (interactive message count)
  (if interactive
      (message message count)
    count))

;;;###autoload
(defun nasy/kill-all-buffers (&optional buffer-list interactive)
  "Kill all buffers and closes their windows.
If the prefix arg is passed, doesn't close windows and only kill buffers that
belong to the current project."
  (interactive
   (list (if current-prefix-arg
             (nasy/project-buffer-list)
           (nasy/buffer-list))
         t))
  (if (null buffer-list)
      (message "No buffers to kill")
    (save-some-buffers)
    (delete-other-windows)
    (when (memq (current-buffer) buffer-list)
      (switch-to-buffer (nasy/fallback-buffer)))
    (mapc #'kill-buffer buffer-list)
    (nasy/message-or-count
     interactive "Killed %d buffers"
     (- (length buffer-list)
        (length (cl-remove-if-not #'buffer-live-p buffer-list))))))

;;;###autoload
(defun nasy/kill-other-buffers (&optional buffer-list interactive)
  "Kill all other buffers (besides the current one).
If the prefix arg is passed, kill only buffers that belong to the current
project."
  (interactive
   (list (delq (current-buffer)
               (if current-prefix-arg
                   (nasy/project-buffer-list)
                 (nasy/buffer-list)))
         t))
  (mapc #'nasy/kill-buffer-and-windows buffer-list)
  (nasy/message-or-count
   interactive "Killed %d other buffers"
   (- (length buffer-list)
      (length (cl-remove-if-not #'buffer-live-p buffer-list)))))

;;;###autoload
(defun nasy/kill-matching-buffers (pattern &optional buffer-list interactive)
  "Kill buffers that match PATTERN in BUFFER-LIST.
If the prefix arg is passed, only kill matching buffers in the current project."
  (interactive
   (list (read-regexp "Buffer pattern: ")
         (if current-prefix-arg
             (nasy/project-buffer-list)
           (nasy/buffer-list))
         t))
  (nasy/kill-matching-buffers pattern buffer-list)
  (when interactive
    (message "Killed %d buffer(s)"
             (- (length buffer-list)
                (length (cl-remove-if-not #'buffer-live-p buffer-list))))))

;;;###autoload
(defun nasy/kill-buried-buffers (&optional buffer-list interactive)
  "Kill buffers that are buried.
If PROJECT-P (universal argument), only kill buried buffers belonging to the
current project."
  (interactive
   (list (nasy/buried-buffers
          (if current-prefix-arg (nasy/project-buffer-list)))
         t))
  (mapc #'kill-buffer buffer-list)
  (nasy/message-or-count
   interactive "Killed %d buried buffers"
   (- (length buffer-list)
      (length (cl-remove-if-not #'buffer-live-p buffer-list)))))

;;;###autoload
(defun nasy/kill-project-buffers (project &optional interactive)
  "Kill buffers for the specified PROJECT."
  (interactive
   (list (if-let (open-projects (nasy/open-projects))
             (completing-read
              "Kill buffers for project: " open-projects
              nil t nil nil
              (if-let* ((project-root (nasy/project-root))
                        (project-root (abbreviate-file-name project-root))
                        ((member project-root open-projects)))
                  project-root))
           (message "No projects are open!")
           nil)
         t))
  (when project
    (let ((buffer-list (nasy/project-buffer-list project)))
      (nasy/kill-buffers-fixup-windows buffer-list)
      (nasy/message-or-count
       interactive "Killed %d project buffers"
       (- (length buffer-list)
          (length (cl-remove-if-not #'buffer-live-p buffer-list)))))))

Core Text

Functions
;;;###autoload
(defun nasy/delete-backward-word (arg)
  "Like `backward-kill-word', but doesn't affect the kill-ring."
  (interactive "p")
  (let (kill-ring)
    (backward-kill-word arg)))

;;;###autoload
(defun nasy/region-active-p ()
  "Return non-nil if selection is active."
  (declare (side-effect-free t))
  (use-region-p))

;;;###autoload
(defun nasy/region-beginning ()
  "Return beginning position of selection."
  (declare (side-effect-free t))
  (region-beginning))

;;;###autoload
(defun nasy/region-end ()
  "Return end position of selection."
  (declare (side-effect-free t))
  (region-end))

;;;###autoload
(defun nasy/thing-at-point-or-region (&optional thing prompt)
  "Grab the current selection, THING at point, or xref identifier at point.
Returns THING if it is a string. Otherwise, if nothing is found at point and
PROMPT is non-nil, prompt for a string (if PROMPT is a string it'll be used as
the prompting string). Returns nil if all else fails.
NOTE: Don't use THING for grabbing symbol-at-point. The xref fallback is smarter
in some cases."
  (declare (side-effect-free t))
  (cond ((stringp thing)
         thing)
        ((nasy/region-active-p)
         (buffer-substring-no-properties
          (nasy/region-beginning)
          (nasy/region-end)))
        (thing
         (thing-at-point thing t))
        ((require 'xref nil t)
         ;; A little smarter than using `symbol-at-point', though in most cases,
         ;; xref ends up using `symbol-at-point' anyway.
         (xref-backend-identifier-at-point (xref-find-backend)))
        (prompt
         (read-string (if (stringp prompt) prompt "")))))

;;;###autoload
(defalias 'default/newline #'newline)

;;;###autoload
(defun default/newline-above ()
  "Insert an indented new line before the current one."
  (interactive)
  (beginning-of-line)
  (save-excursion (newline))
  (indent-according-to-mode))

;;;###autoload
(defun default/newline-below ()
  "Insert an indented new line after the current one."
  (interactive)
  (end-of-line)
  (newline-and-indent))

;;;###autoload
(defun default/yank-pop ()
  "Interactively select what text to insert from the kill ring."
  (interactive)
  (call-interactively
   (cond ((fboundp 'counsel-yank-pop)    #'counsel-yank-pop)
         ((fboundp 'helm-show-kill-ring) #'helm-show-kill-ring)
         ((error "No kill-ring search backend available. Enable ivy or helm!")))))

;;;###autoload
(defun default/yank-buffer-filename ()
  "Copy the current buffer's path to the kill ring."
  (interactive)
  (if-let* ((filename (or buffer-file-name (bound-and-true-p list-buffers-directory))))
      (message (kill-new (abbreviate-file-name filename)))
    (error "Couldn't find filename in current buffer")))

;;;###autoload
(defun default/insert-file-path (arg)
  "Insert the file name (absolute path if prefix ARG).
If `buffer-file-name' isn't set, uses `default-directory'."
  (interactive "P")
  (let ((path (or buffer-file-name default-directory)))
    (insert
     (if arg
         (abbreviate-file-name path)
       (file-name-nondirectory path)))))

;;;###autoload
(defun default/newline-indent-and-continue-comments-a ()
  "A replacement for `newline-and-indent'.
Continues comments if executed from a commented line, with special support for
languages with weak native comment continuation support (like C-family
languages)."
  (interactive)
  (if (and (sp-point-in-comment)
           comment-line-break-function)
      (funcall comment-line-break-function nil)
    (delete-horizontal-space t)
    (newline nil t)
    (indent-according-to-mode)))

core others

Functions
Default
;;;###autoload
(defun nasy/lsp-format-region-or-buffer ()
  "Format the buffer (or selection) with LSP."
  (interactive)
  (unless (bound-and-true-p lsp-mode)
    (user-error "Not in an LSP buffer"))
  (call-interactively
   (if (nasy/region-active-p)
       #'lsp-format-region
     #'lsp-format-buffer)))
Project Related
;;;###autoload
(defun nasy/project-p (&optional dir)
  "Return t if DIR (defaults to `default-directory') is a valid project."
  (and (nasy/project-root dir)
       t))

;;;###autoload
(defun nasy/project-root (&optional dir)
  "Return the project root of DIR (defaults to `default-directory').
Returns nil if not in a project."
  (let ((projectile-project-root (unless dir projectile-project-root))
        projectile-require-project-root)
    (projectile-project-root dir)))

Define Nasy Custom

(require 'nasy-core-custom)

Here includes all of the customizable variables and faces of my configuration.

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

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

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

(add-hook 'nasy/config-after-hook
          #'(lambda () (message "Hi~ Hope you have fun with this config.")))
Custom
(defgroup nasy nil
  "Nasy Emacs Custom Configurations."
  :group 'emacs)

(defcustom lisp-modes-hooks '(common-lisp-mode-hook
                              emacs-lisp-mode-hook
                              lisp-mode-hook
                              racket-mode-hook
                              scheme-mode-hook)
  "List of lisp-related modes hooks."
  :type '(repeat symbol)
  :group 'nasy)

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

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

(defvar *eldoc-use* 'eldoc-overlay
  "Use eldoc-box, eldoc-overlay or not.

nil means use default.

box means use eldoc-box.

overlay means use eldoc-overlay.")

(defvar *flycheck-inline* t
  "Use flycheck-inline or not.")

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

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

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

(defcustom *highlight-indent-guides* t
  "Whether to use highlight-indent-guides or not."
  :group 'nasy
  :type 'boolean)

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

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

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

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

(defcustom *pyblack* nil
  "Whether to use black to reformat python or not."
  :group 'nasy
  :type 'boolean)

(defcustom *py-module* 'elpy
  "Select py module."
  :group 'nasy
  :type '(choice (const :tag "Use elpy"   elpy)
                 (const :tag "Use pyls"   pyls)
                 (const :tag "Use mspyls" mspyls)))


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

(defcustom *ivy/helm/selectrum* 'selectrum
  "Use ivy, helm or selectrum?"
  :group 'nasy
  :type '(choice (const :tag "Use ivy"       ivy)
                 (const :tag "Use helm"      helm)
                 (const :tag "Use selectrum" selectrum)))

(defcustom *ivy-or-helm* 'ivy
  "Use ivy or helm?"
  :group 'nasy
  :type '(choice (const :tag "Use ivy"  ivy)
                 (const :tag "Use helm" helm)))

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

(defcustom *ivy-fuzzy* nil
  "Enables fuzzy completion for Ivy searches."
  :group 'nasy
  :type  'boolean)

(defcustom *ivy-prescient* t
  "Enables prescient filtering and sorting for Ivy searches."
  :group 'nasy
  :type  'boolean)

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

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

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

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

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

(defcustom *dvorak-trans* nil
    "Whether to trans dvorak to qwerty key-bindings or not."
    :group 'nasy
    :type 'boolean)

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

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

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

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

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

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

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

(defcustom *lookup/offline* t
  "Install and prefer offline dictionary/thesaurus."
  :group 'nasy
  :type 'boolean)

(defvar nasy/projectile-fd-binary
  (or (cl-find-if #'executable-find '("fdfind" "fd"))
      "fd")
  "name of `fd-find' executable binary")
Default Settings
Emacs
(leaf nasy-emacs-settings
  :init
  (leaf cus-edit
    :custom
    (custom-raised-buttons . t)))
Company
(setq-default
 company-idle-delay .5)
Cursor
(setq-default
  blink-cursor-interval .6
  blink-matching-paren  t
  cursor-in-non-selected-windows t)

(blink-cursor-mode 1)

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

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

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

(global-auto-revert-mode t)

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


(add-hook 'nasy/config-after-hook  #'nasy/config-after)
Custom Faces

##+begin_src elisp (defun nasy/set-face () "Set custom face." (after-x 'org (set-face-attribute 'org-meta-line nil :slant 'italic) (set-face-attribute 'org-block-begin-line nil :slant 'italic) (set-face-attribute 'org-block-end-line nil :slant 'italic)

(when org-headline-rescale (set-face-attribute 'org-level-1 nil :height 1.5 :inherit 'outline-1) (set-face-attribute 'org-level-2 nil :height 1.3 :inherit 'outline-2) (set-face-attribute 'org-level-3 nil :height 1.2 :inherit 'outline-3) (set-face-attribute 'org-level-4 nil :height 1.1 :inherit 'outline-4)))

(set-face-attribute 'font-lock-comment-face nil :slant 'italic) (set-face-attribute 'font-lock-keyword-face nil :slant 'italic) (set-face-attribute 'font-lock-builtin-face nil :slant 'italic) (set-face-attribute 'show-paren-match nil :background "#a1de93" :foreground "#705772" :weight 'ultra-bold)

(after-x 'tab-line (set-face-attribute 'tab-line nil :background "#303946" :foreground "#F4FFC9")

(set-face-attribute 'tab-line-tab nil :background "#3C78D8")

(set-face-attribute 'tab-line-tab-current nil :background "#FFFC67" :foreground "#222831" :inherit 'tab-line-tab)

(set-face-attribute 'tab-line-tab-inactive nil :background "#5FF967" :foreground "#222831" :inherit 'tab-line-tab))

(after-x 'smartparens-config (set-face-attribute 'sp-show-pair-match-face nil :background "#a1de93" :foreground "#705772" :weight 'ultra-bold)))

(add-hook 'nasy/config-after-hook #'nasy/set-face) #+end_src

Key Definition and Bindings

(require 'nasy-core-keybindings)
General

More convenient key definitions in emacs.

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

(leaf general
  :doc "More convenient key definitions in emacs."
  :url "https://github.com/noctuid/general.el"
  :commands gsetq gsetq-local gsetq-default
  :init
  (defalias 'gsetq #'general-setq)
  (defalias 'gsetq-local #'general-setq-local)
  (defalias 'gsetq-default #'general-setq-default))
Transient

Transient commands.

https://github.com/magit/transient

(leaf transient
  :doc "Transient commands."
  :url "https://github.com/magit/transient."
  :commands transient-define-prefix
  :custom (transient-default-level . 5))
define nasy-map
(defvar nasy-map
  (let ((map (make-sparse-keymap)))
    map)
  "Nasy Keymaps.")

(eval-and-compile
  (general-create-definer nasy-def
    :prefix "C-c"
    :prefix-map 'nasy-map))


(defmacro n/map (key name desc &rest rest)
  "Nasy keymap define macro."
  (let ((n/name (format "nasy/%s" name)))
    (let ((keymap (intern (concat n/name "-map")))
          (def    (intern (concat n/name "-def"))))
     `(progn
        (defvar ,keymap (make-sparse-keymap) ,desc)
        (nasy-def ,key '(:keymap ,keymap :wk ,n/name))
        (general-create-definer ,def
          :keymaps ',keymap)
        (,def ,@rest)))))
Key Bindings
global map
(general-define-key
 "C-."  #'imenu

 ;;; newlines
 [remap newline]  #'newline-and-indent
 "C-j"            #'default/newline

 ;; search
 "C-s"    (cond
           ((eq *ivy-or-helm* 'ivy)
            #'swiper-isearch)
           ((eq *ivy-or-helm* 'helm)
            #'swiper-helm)
           (t #'isearch-forward))
 "C-S-s"  (cond
           ((eq *ivy-or-helm* 'ivy)
            #'swiper-isearch-thing-at-point))
 "C-r"    (cond
           ((eq *ivy-or-helm* 'ivy)
            #'ivy-resume)
           ((eq *ivy-or-helm* 'helm)
            #'helm-resume)
           (t #'isearch-backward))

 ;;; buffers
 "C-x b"    #'switch-to-buffer
 "C-x 4 b"  #'switch-to-buffer-other-window
 "C-x C-b"  #'ibuffer-list-buffers
 "C-x K"    #'nasy/kill-this-buffer-in-all-windows)
macOS Special Key Bindings
(leaf mac-keybind
  :tag "virtual"
  :when *is-a-mac*
  :custom
  (mac-option-modifier        . 'meta)
  (mac-command-modifier       . 'hyper)
  (mac-right-command-modifier . 'super)
  (mac-function-modifier      . 'super)
  :bind
  ("C-z" . stop-minimizing-window)

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

   ;; text Operations
  ("H-a" . mark-whole-buffer)
  ("H-v" . yank)
  ("H-c" . kill-ring-save)
  ("H-s" . save-buffer)
  ("H-z" . undo)
  ("H-w" . delete-window)
  ("H-<backspace>" . n/kill-line-0)
  :init
  ;; unset
  (defun n/kill-line-0 ()
    (interactive)
    (kill-line 0))
  (global-unset-key (kbd "<magnify-down>"))
  (global-unset-key (kbd "<magnify-up>")))
Mouse Key Bindings
(general-define-key
 "<mouse-4>" (lambda () (scroll-down 1))
 "<mouse-5>" (lambda () (scroll-up 1)))
code map
(n/map
 "c" "code" "Nasy code keymap"
 "c" #'compile
 "C" #'recompile
 "k" #'nasy/lookup/documentation

 "x" #'flycheck-list-errors

 "a" #'lsp-excute-code-action
 "f" #'nasy/lsp-format-region-or-buffer
 "i" #'lsp-organize-imports
 "r" #'lsp-rename
 "j" (cond
      ((eq *ivy-or-helm* 'ivy)
       #'lsp-ivy-workspace-symbol)
      ((eq *ivy-or-helm* 'helm)
       #'helm-ivy-workspace-symbol))
 "J" (cond
      ((eq *ivy-or-helm* 'ivy)
       #'lsp-ivy-global-workspace-symbol)
      ((eq *ivy-or-helm* 'helm)
       #'helm-ivy-global-workspace-symbol)))
Company
(general-define-key
 "C-;"  #'nasy/company-complete)

(general-define-key
 :keymaps 'company-active-map
 "C-o"        #'company-search-kill-others
 "C-n"        #'company-select-next
 "C-p"        #'company-select-previous
 "C-h"        #'company-quickhelp-manual-begin
 "C-S-h"      #'company-show-doc-buffer
 "C-s"        #'company-search-candidates
 "M-s"        #'company-filter-candidates
 [C-tab]      #'nasy/company-complete
 [tab]        #'company-complete-common-or-cycle
 [backtab]    #'company-select-previous
 [C-return]   #'counsel-company)

(general-define-key
 :keymaps 'company-search-map
 "C-n"        #'company-search-repeat-forward
 "C-p"        #'company-search-repeat-backward
 "C-s"        (lambda () (company-search-abort) (company-filter-candidates)))
file map
(n/map
 "f" "file" "Nasy file keymap")
Treemacs
(n/map
 "t" "n-treemacs" "Nasy treemacs keymap"
 "1" #'treemacs-delete-other-windows
 "t" #'treemacs
 "B" #'treemacs-bookmark
 "f" #'treemacs-find-file
 "T" #'treemacs-find-tag)

Mixed

(require 'nasy-core-mixed)
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))
History, Saving, Desktop and Session
(leaf savehist
  :hook after-init-hook
  :custom
  (kill-ring-max              . 300)
  (history-length             . 3000)
  (history-delete-duplicates  . t)
  (savehist-autosave-interval . 60)
  (savehist-additional-variables
   . '(mark-ring
       global-mark-ring
       search-ring
       regexp-search-ring
       extended-command-history)))

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

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

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

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

  (defun stop-minimizing-window ()
    "Stop minimizing window under macOS."
    (interactive)
    (unless (and *is-a-mac*
                 window-system)
      (suspend-frame))))
Minibuffer
(setq enable-recursive-minibuffers t)

(add-hook #'after-init-hook #'(lambda () (minibuffer-depth-indicate-mode 1)))

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

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


(straight-use-package 'exec-path-from-shell)
(leaf exec-path-from-shell
  :init
  ;; 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)
  :custom
  (shell-command-switch . "-ic")
  (shell-file-name      . "zsh")
  ((exec-path-from-shell-arguments
    exec-path-from-shell-check-startup-files) . nil)
  :config
  (exec-path-from-shell-initialize)
  (add-to-list 'exec-path "~/.pyenv/shims/"))
Text Scale
(leaf default-text-scale
  :commands default-text-scale-mode
  :hook after-init-hook)
Compile
;; https://github.com/jwiegley/emacs-async
(leaf dired-async
  :commands dired-async-mode)

(leaf compile
  :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)))


  (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))))
  :bind (([f6] . recompile))
  :hook ((compilation-finish-functions . alert-after-compilation-finish)))

Window

Switch-Window

Offer a visual way to choose a window to switch to.

https://github.com/dimitri/switch-window

(leaf switch-window
  :doc "Offer a *visual* way to choose a window to switch to."
  :url "https://github.com/dimitri/switch-window"
  :bind
  ("C-x o" . switch-window)
  ("C-x 1" . toggle-delete-other-windows)
  ("C-x 2" . split-window-v)
  ("C-x 3" . split-window-h)
  ("C-x |" . split-window-horizontally-instead)
  ("C-x _" . split-window-vertically-instead)
  ("C-x x" . nasy/split-window)
  ("M-o"   . transient-dwim--switch-window)
  :custom
  (switch-window-shortcut-style . 'alphabet)
  (switch-window-timeout        . nil)
  :transient
  (transient-dwim--switch-window
   ()
   "Transient-dwim for `switch-window'."
   [["Switch Window"
     ("o" "Switch Window" switch-window)]])
  :config
  ;; When splitting window, show (other-buffer) in the new window
  (defun split-window-func-with-other-buffer (split-function)
    "Split window with `SPLIT-FUNCTION'."
    (lambda (&optional arg)
      "Split this window and switch to the new window unless ARG is provided."
      (interactive "P")
      (funcall split-function)
      (let ((target-window (next-window)))
        (set-window-buffer target-window (other-buffer))
        (unless arg
          (select-window target-window)))))

  (defun split-window-v ()
    (split-window-func-with-other-buffer 'split-window-vertically))

  (defun split-window-h ()
    (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)))

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

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

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

Editor

(nasy/local-repo editor)
(require 'nasy-editor)

Here is the editor's configuration, including keywords: comm, data, diff, docs, emacs, extensions, faces, files, help, hypermedia, indentation, killing, libs, lists, location, marking, region, navigation, performance, vc, and window.

Packages

Packages list

  • alert
  • ansi-color
  • auto-compress
  • cheat-sh
  • dash
  • dired
    • dired-hack
  • easy-kill
  • eldoc
    • eldoc-overlay (optional)
    • eldoc-box (optional)
  • expand-region
  • explain-pause-mode
  • fill-column
    • Unfill
    • visual-fill-column
  • highlight
    • color-identifiers-mode
    • hl-line (builtin)
    • highlight-indent-guides
    • rainbow-mode
  • helm
  • helpful
  • htmlize
  • indent-tools
  • ivy/swiper/counsel
    • all-the-icons-ivy-rich
    • counsel-projectile
    • ivy-prescient (optional)
    • ivy-rich
    • ivy-xref
  • list-unicode-display
  • mmm-mode
  • multiple-cursors
  • page-break-lines
  • paren
    • smartparens
    • rainbow-delimiters
  • point-history
  • pretty-mode
  • prescient
  • quick-peek
  • switch-window
  • symbol-overlay
  • treemacs
    • treemacs-icons-dired
    • treemacs-magit
    • treemacs-projectile
  • tree-sitter
  • version-control
    • abridge-diff
    • forge
    • gist
    • git-blamed
    • git-gutter
    • git-messager
    • git-modes
    • git-timemachine
    • magit
    • magit-org-todos
    • magit-todos
  • which-key
  • whitespace-cleanup-mode
  • yasnippet
    • yasnippet-snippets
(straight-register-package
 '(tree-sitter :host github
               :repo "ubolonton/emacs-tree-sitter"
               :files ("lisp/*.el" "langs/*.el" "langs/queries")))

(straight-register-package
 '(point-history :type git
                 :host github
                 :repo "blue0513/point-history"))

(nasy/s-u-p
  alert
  cheat-sh
  dash
  diff-hl
  dired-hacks
  easy-kill
  *eldoc-use*
  explain-pause-mode
  expand-region
  ;; fill
  unfill
  visual-fill-column
  ;; highlight
  color-identifiers-mode
  ;; hl-line  builtin
  highlight-indent-guides
  rainbow-mode
  ;; helm
  ;; helm

  helpful
  htmlize
  indent-tools
  ;; ivy
  all-the-icons-ivy-rich
  counsel
  counsel-projectile
  ivy
  ivy-rich
  ivy-xref
  (:when *ivy-prescient* prescient ivy-prescient)

  list-unicode-display
  mmm-mode
  multiple-cursors
  page-break-lines
  ;; paren
  smartparens
  rainbow-delimiters

  point-history
  prescient
  pretty-mode
  quick-peek
  symbol-overlay
  switch-window
  ;; treemacs
  treemacs
  treemacs-icons-dired
  treemacs-magit
  treemacs-projectile

  tree-sitter
  ;;version-control
  abridge-diff
  forge
  gist
  git-blamed
  git-gutter
  git-messenger
  git-modes
  git-timemachine
  magit
  magit-org-todos
  magit-todos

  which-key
  whitespace-cleanup-mode
  yasnippet
  yasnippet-snippets)

Updates

<Tue, Aug 04, 2020>

Removed better jump

Configs

alert

A Growl-like alerts notifier for Emacs

https://github.com/jwiegley/alert

(leaf alert
  :doc "A Growl-like alerts notifier for Emacs."
  :url "https://github.com/jwiegley/alert"
  :tag "notification" "emacs" "message"
  :custom
  (alert-default-style . 'osx-notifier))
ansi-color

ansi-color.el translates ANSI SGR (Select Graphic Rendition) escape sequences like "Esc[30m" into EmacsOverlays, TextProperties, or XEmacsExtents with face colours, bold, etc.

https://www.emacswiki.org/emacs/AnsiColor

(leaf ansi-color
  :doc "ansi-color.el translates ANSI SGR (Select Graphic Rendition) escape sequences
with face colours, bold, etc."
  :url "https://www.emacswiki.org/emacs/AnsiColor"
  :tag "comm" "processes" "terminals" "services"
  :commands colourise-compilation-buffer
  :hook ((compilation-filter-hook . colourise-compilation-buffer))
  :config
  (eval-and-compile
    (defun colourise-compilation-buffer ()
      (when (eq major-mode 'compilation-mode)
        (ansi-cOLOR-APPLY-on-region compilation-filter-start
                                    (point-max))))))
auto-compress
(leaf jka-cmpr
  :tag "builtin"
  :hook (after-init-hook . auto-compression-mode))
Cheat Sh

Simple Emacs interface for cheat.sh.

https://github.com/davep/cheat-sh.el

(leaf cheat-sh
  :doc "Simple Emacs interface for cheat.sh"
  :url "https://github.com/davep/cheat-sh.el"
  :tag "docs" "help")
Dash

A modern list library for Emacs.

https://github.com/magnars/dash.el

(leaf dash
  :doc "A modern list library for Emacs."
  :url "https://github.com/magnars/dash.el"
  :tag "lists"
  :defer-config
  (dash-enable-font-lock))
Dired
(leaf nasy-editor-dired
  :require t)
Dired

DiredMode is the mode of a Dired buffer. It shows a directory (folder) listing that you can use to perform various operations on files and subdirectories in the directory. The operations you can perform are numerous, from creating subdirectories to byte-compiling files, searching files, and of course visiting (editing) files.

https://www.emacswiki.org/emacs/DiredMode

(leaf dired
  :doc "DiredMode is the mode of a Dired buffer."
  :url "https://www.emacswiki.org/emacs/DiredMode"
  :tag "files"
  :bind
  (:dired-mode-map
   ([mouse-2] . dired-find-file)
   ("C-c C-p" . wdired-change-to-wdired-mode))
  :custom
  `(insert-directory-program . ,(or (executable-find "gls")
                                   (executable-find "ls")))
  (dired-recursive-deletes  . 'top))
Dired Hacks

Collection of useful dired additions

https://github.com/Fuco1/dired-hacks

(leaf dired-hacks
  :doc "Collection of useful dired additions"
  :url "https://github.com/Fuco1/dired-hacks"
  :tag "files")
  • Dired Filter
    (leaf dired-filter
      :tag "files"
      :bind
      (:dired-mode-map
       ("/" . dired-filter-map))
      (:dired-filter-map
       ("p" . dired-filter-pop-all)
       ("/" . dired-filter-mark-map))
      :hook (dired-mode-hook
             (dired-mode-hook . dired-filter-group-mode))
      :custom
      (dired-filter-revert . 'never)
      (dired-filter-group-saved-groups
       . '(("default"
            ("Git"
             (directory . ".git")
             (file . ".gitignore"))
            ("Directory"
             (directory))
            ("PDF"
             (extension . "pdf"))
            ("LaTeX"
             (extension "tex" "bib"))
            ("Source"
             (extension "c" "cpp" "hs" "rb" "py" "r" "cs" "el" "lisp" "html" "js" "css"))
            ("Doc"
             (extension "md" "rst" "txt"))
            ("Org"
             (extension . "org"))
            ("Archives"
             (extension "zip" "rar" "gz" "bz2" "tar"))
            ("Images"
             (extension "jpg" "JPG" "webp" "png" "PNG" "jpeg" "JPEG" "bmp" "BMP" "TIFF" "tiff" "gif" "GIF"))))))
    
  • Dired Rainbow
    (leaf dired-rainbow
      :tag "files"
      :commands dired
      :defer-config
      (dired-rainbow-define html "#eb5286"
                            ("css" "less" "sass" "scss" "htm" "html" "jhtm" "mht" "eml" "mustache" "xhtml"))
      (dired-rainbow-define xml "#f2d024"
                            ("xml" "xsd" "xsl" "xslt" "wsdl" "bib" "json" "msg" "pgn" "rss" "yaml" "yml" "rdata"))
      (dired-rainbow-define document "#9561e2"
                            ("docm" "doc" "docx" "odb" "odt" "pdb" "pdf" "ps" "rtf" "djvu" "epub" "odp" "ppt" "pptx"))
      (dired-rainbow-define markdown "#ffed4a"
                            ("org" "etx" "info" "markdown" "md" "mkd" "nfo" "pod" "rst" "tex" "textfile" "txt"))
      (dired-rainbow-define database "#6574cd"
                            ("xlsx" "xls" "csv" "accdb" "db" "mdb" "sqlite" "nc"))
      (dired-rainbow-define media "#de751f"
                            ("mp3" "mp4" "MP3" "MP4" "avi" "mpeg" "mpg" "flv" "ogg" "mov" "mid" "midi" "wav" "aiff" "flac"))
      (dired-rainbow-define image "#f66d9b"
                            ("tiff" "tif" "cdr" "gif" "ico" "jpeg" "jpg" "png" "psd" "eps" "svg"))
      (dired-rainbow-define log "#c17d11"
                            ("log"))
      (dired-rainbow-define shell "#f6993f"
                            ("awk" "bash" "bat" "sed" "sh" "zsh" "vim"))
      (dired-rainbow-define interpreted "#38c172"
                            ("py" "ipynb" "rb" "pl" "t" "msql" "mysql" "pgsql" "sql" "r" "clj" "cljs" "scala" "js"))
      (dired-rainbow-define compiled "#4dc0b5"
                            ("asm" "cl" "lisp" "el" "c" "h" "c++" "h++" "hpp" "hxx" "m" "cc" "cs" "cp" "cpp" "go" "f" "for" "ftn" "f90" "f95" "f03" "f08" "s" "rs" "hi" "hs" "pyc" ".java"))
      (dired-rainbow-define executable "#8cc4ff"
                            ("exe" "msi"))
      (dired-rainbow-define compressed "#51d88a"
                            ("7z" "zip" "bz2" "tgz" "txz" "gz" "xz" "z" "Z" "jar" "war" "ear" "rar" "sar" "xpi" "apk" "xz" "tar"))
      (dired-rainbow-define packaged "#faad63"
                            ("deb" "rpm" "apk" "jad" "jar" "cab" "pak" "pk3" "vdf" "vpk" "bsp"))
      (dired-rainbow-define encrypted "#ffed4a"
                            ("gpg" "pgp" "asc" "bfe" "enc" "signature" "sig" "p12" "pem"))
      (dired-rainbow-define fonts "#6cb2eb"
                            ("afm" "fon" "fnt" "pfb" "pfm" "ttf" "otf"))
      (dired-rainbow-define partition "#e3342f"
                            ("dmg" "iso" "bin" "nrg" "qcow" "toast" "vcd" "vmdk" "bak"))
      (dired-rainbow-define vc "#0074d9"
                            ("git" "gitignore" "gitattributes" "gitmodules"))
      (dired-rainbow-define-chmod directory "#6cb2eb" "d.*")
      (dired-rainbow-define-chmod executable-unix "#38c172" "-.*x.*"))
    
  • Dired Narrow
    (leaf dired-narrow
      :tag "files"
      :bind ((:dired-narrow-map
              ("<down>"  . dired-narrow-next-file)
              ("<up>"    . dired-narrow-previous-file)
              ("<right>" . dired-narrow-enter-directory))))
    
  • Dired Collapse
    (leaf dired-collapse
      :tag "files"
      :hook dired-mode-hook)
    
Easy Kill

Provide commands easy-kill and easy-mark to let users kill or mark things easily.

https://github.com/leoliu/easy-kill

(leaf easy-kill
  :doc "Kill & Mark Things Easily in Emacs."
  :url "https://github.com/leoliu/easy-kill"
  :tag "killing" "convenience"
  :bind (([remap kill-ring-save]
          . easy-kill)
         ([remap mark-sexp]
          . easy-mark)))
Eldoc
eldoc box

This package displays ElDoc documentations in a childframe.

https://github.com/casouri/eldoc-box

(leaf eldoc-box
  :doc "This package displays ElDoc documentations in a childframe."
  :url "https://github.com/casouri/eldoc-box"
  :tag "extensions"
  :when (eq *eldoc-use* 'eldoc-box)
  :hook ((eldoc-mode-hook . eldoc-box-hover-mode)
         (eldoc-mode-hook . eldoc-box-hover-at-point-mode)))
eldoc overlay

Display eldoc doc with contextual documentation overlay for easy to look.

https://github.com/stardiviner/eldoc-overlay

(leaf eldoc-overlay
  :doc "Display eldoc doc with contextual documentation overlay for easy to look."
  :url "https://github.com/stardiviner/eldoc-overlay"
  :tag "extensions"
  :when (eq *eldoc-use* 'eldoc-overlay)
  :hook eldoc-mode-hook)
Expand Region

Emacs extension to increase selected region by semantic units.

https://github.com/magnars/expand-region.el

(leaf expand-region
  :doc "Emacs extension to increase selected region by semantic units."
  :url "https://github.com/magnars/expand-region.el"
  :tag "marking region"
  :bind
  ("C-=" . er/expand-region))
explain-pause-mode

top, but for Emacs.

https://github.com/lastquestion/explain-pause-mode

(leaf explain-pause-mode
  :doc "top, but for Emacs."
  :url "https://github.com/lastquestion/explain-pause-mode"
  :tag "performance" "speed" "config")
Files   builtin files
(leaf files
  :tag "builtin" "files"
  :custom (find-file-visit-truename . t))
Fill Column
(leaf fill
  :doc "Filling text."
  :tag "emacs")
Unfill

Functions providing the inverse of Emacs' fill-paragraph and fill-region

https://github.com/purcell/unfill

(leaf unfill
  :doc "Functions providing the inverse of Emacs' fill-paragraph and fill-region"
  :url "https://github.com/purcell/unfill"
  :tag "convenience"
  :bind (("M-q" . unfill-toggle)))
Visual-fill-column

Emacs mode for wrapping visual-line-mode buffers at fill-column.

https://github.com/joostkremers/visual-fill-column

(leaf visual-fill-column
  :doc "Emacs mode for wrapping visual-line-mode buffers at fill-column."
  :url "https://github.com/joostkremers/visual-fill-column"
  :tag "convenience"
  :commands maybe-adjust-visual-fill-column
  :hook (visual-line-mode-hook
         (visual-fill-column-mode-hook . maybe-adjust-visual-fill-column))
  :config
  (defun maybe-adjust-visual-fill-column nil
    "Readjust visual fill column when the global font size is modified.\nThis 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))))
Fuz.el

Fast and precise fuzzy scoring/matching utils for Emacs, powered by rust

https://github.com/rustify-emacs/fuz.el

Highlight
Color Identifiers Mode

Emacs minor mode to highlight each source code identifier uniquely based on its name.

https://github.com/ankurdave/color-identifiers-mode

(leaf color-identifiers-mode
  :doc "Emacs minor mode to highlight each source code identifier uniquely based
on its name."
  :url "https://github.com/ankurdave/color-identifiers-mode"
  :tag "faces" "languages"
  :hook prog-mode-hook)
hl-line

Highlight the current line of characters.

https://www.emacswiki.org/emacs/HighlightCurrentLine

(leaf hl-line
  :doc "Highlight the current line of characters."
  :url "https://www.emacswiki.org/emacs/HighlightCurrentLine"
  :tag "faces" "frames" "emulations"
  :hook ((after-init-hook . global-hl-line-mode)))
Highlight Indent Guides

Emacs minor mode to highlight indentation.

https://github.com/DarthFennec/highlight-indent-guides

(leaf highlight-indent-guides
  :doc "Emacs minor mode to highlight indentation."
  :url "https://github.com/DarthFennec/highlight-indent-guides"
  :tag "faces"
  :when *highlight-indent-guides*
  :hook (prog-mode-hook-hook text-mode-hook-hook org-mode-hook-hook)
  :config
  (highlight-indent-guides-responsive . nil)
  (highlight-indent-guides-delay      . 0.5))
Rainbow-Mode

This minor mode sets background color to strings that match color names, e.g. #0000ff is displayed in white with a blue background.

(leaf rainbow-mode
  :doc "Colorize color names in buffers."
  :url "https://elpa.gnu.org/packages/rainbow-mode.html"
  :tag "faces"
  :hook (after-init-hook
         text-mode-hook
         org-mode-hook
         css-mode-hook
         html-mode-hook
         prog-mode-hook)
  :defer-config
  (when (fboundp 'diminish)
    (diminish 'rainbow-mode)))
Helpful

A better Emacs help buffer.

https://github.com/Wilfred/helpful

(leaf helpful
  :doc "A better Emacs *help* buffer."
  :url "https://github.com/Wilfred/helpful"
  :tag "help" "lisp"
  :bind (("C-c C-d" . helpful-at-point)))
         ;; Use ivy instead
         ;; ([remap describe-function]   . helpful-callable)
         ;; ([remap describe-variable]   . helpful-variable)
         ;; ([remap describe-bindings]   . helpful-key)))
Htmlize

Convert buffer text and decorations to HTML.

https://github.com/hniksic/emacs-htmlize

(leaf htmlize
  :doc "Convert buffer text and decorations to HTML."
  :url "https://github.com/hniksic/emacs-htmlize"
  :tag "hypermedia" "extensions"
  :custom (htmlize-pre-style . t))
indent-tools

Emacs mode to indent, navigate around and act on indentation units: perfect for yaml, python and the like.

https://gitlab.com/emacs-stuff/indent-tools

(leaf indent-tools
  :doc "Emacs mode to indent, navigate around and act on indentation units:
perfect for yaml, python and the like."
  :url "https://gitlab.com/emacs-stuff/indent-tools"
  :tag "indentation" "navigation"
  :bind (("C-c TAB" . indent-tools-hydra/body)))
Ivy, Counsel and Swiper
(require 'nasy-editor-ivy)
Autoloads

Some of them borrowed from doom-emacs

;;;###autoload
(defun nasy/ivy-is-workspace-buffer-p (buffer)
  (let ((buffer (car buffer)))
    (when (stringp buffer)
     (setq buffer (get-buffer buffer)))
    (nasy/workspace-contains-buffer-p buffer)))

;;;###autoload
(defun nasy/ivy-is-workspace-other-buffer-p (buffer)
  (let ((buffer (car buffer)))
    (when (stringp buffer)
     (setq buffer (get-buffer buffer)))
    (and (not (eq buffer (current-buffer)))
       (nasy/workspace-contains-buffer-p buffer))))

;;
;; Library
;;;###autoload
(defun nasy/ivy/switch-buffer-preview ()
  (let (ivy-use-virtual-buffers ivy--virtual-buffers)
    (counsel--switch-buffer-update-fn)))

;;;###autoload
(defalias 'nasy/ivy/switch-buffer-preview-all #'counsel--switch-buffer-update-fn)
;;;###autoload
(defalias 'nasy/ivy/switch-buffer-unwind      #'counsel--switch-buffer-unwind)

;;;###autoload
(defun nasy/ivy--switch-buffer (workspace other)
  (let ((current (not other))
        prompt action filter update unwind)
    (cond ((and workspace current)
           (setq prompt "Switch to workspace buffer: "
                 action #'ivy--switch-buffer-action
                 filter #'nasy/ivy-is-workspace-other-buffer-p))
          (workspace
           (setq prompt "Switch to workspace buffer in other window: "
                 action #'ivy--switch-buffer-other-window-action
                 filter #'nasy/ivy-is-workspace-buffer-p))
          (current
           (setq prompt "Switch to buffer: "
                 action #'ivy--switch-buffer-action))
          ((setq prompt "Switch to buffer in other window: "
                 action #'ivy--switch-buffer-other-window-action)))
    (when nasy/ivy-buffer-preview
      (cond ((not (and ivy-use-virtual-buffers
                    (eq nasy/ivy-buffer-preview 'everything)))
             (setq update #'nasy/ivy/switch-buffer-preview
                   unwind #'nasy/ivy/switch-buffer-unwind))
            ((setq update #'nasy/ivy/switch-buffer-preview-all
                   unwind #'nasy/ivy/switch-buffer-unwind))))
    (ivy-read prompt 'internal-complete-buffer
              :action action
              :predicate filter
              :update-fn update
              :unwind unwind
              :preselect (buffer-name (other-buffer (current-buffer)))
              :matcher #'ivy--switch-buffer-matcher
              :keymap ivy-switch-buffer-map
              ;; NOTE A clever disguise, needed for virtual buffers.
              :caller #'ivy-switch-buffer)))

;;;###autoload
(defun nasy/ivy/switch-workspace-buffer (&optional arg)
  "Switch to another buffer within the current workspace.
If ARG (universal argument), open selection in other-window."
  (interactive "P")
  (nasy/ivy--switch-buffer t arg))

;;;###autoload
(defun nasy/ivy/switch-workspace-buffer-other-window ()
  "Switch another window to a buffer within the current workspace."
  (interactive)
  (nasy/ivy--switch-buffer t t))

;;;###autoload
(defun nasy/ivy/switch-buffer ()
  "Switch to another buffer."
  (interactive)
  (nasy/ivy--switch-buffer nil nil))

;;;###autoload
(defun nasy/ivy/switch-buffer-other-window ()
  "Switch to another buffer in another window."
  (interactive)
  (nasy/ivy--switch-buffer nil t))

;;;###autoload
(defun nasy/ivy-woccur ()
  "Invoke a wgrep buffer on the current ivy results, if supported."
  (interactive)
  (unless (window-minibuffer-p)
    (user-error "No completion session is active"))
  (require 'wgrep)
  (let ((caller (ivy-state-caller ivy-last)))
    (if-let (occur-fn (plist-get nasy/ivy-edit-functions caller))
      (ivy-exit-with-action
       (lambda (_) (funcall occur-fn)))
     (if-let (occur-fn (plist-get ivy--occurs-list caller))
         (let ((buffer (generate-new-buffer
                        (format "*ivy-occur%s \"%s\"*"
                                (if caller (concat " " (prin1-to-string caller)) "")
                                ivy-text))))
           (with-current-buffer buffer
             (let ((inhibit-read-only t))
               (erase-buffer)
               (funcall occur-fn))
             (setf (ivy-state-text ivy-last) ivy-text)
             (setq ivy-occur-last ivy-last)
             (setq-local ivy--directory ivy--directory))
           (ivy-exit-with-action
            `(lambda (_)
               (pop-to-buffer ,buffer)
               (ivy-wgrep-change-to-wgrep-mode))))
       (user-error "%S doesn't support wgrep" caller)))))

;;;###autoload
(defun nasy/ivy-yas-prompt (prompt choices &optional display-fn)
  (yas-completing-prompt prompt choices display-fn #'ivy-completing-read))

;;;###autoload
(defun nasy/ivy-git-grep-other-window-action (x)
  "Opens the current candidate in another window."
  (when (string-match "\\`\\(.*?\\):\\([0-9]+\\):\\(.*\\)\\'" x)
    (select-window
     (with-ivy-window
      (let ((file-name   (match-string-no-properties 1 x))
            (line-number (match-string-no-properties 2 x)))
        (find-file-other-window (expand-file-name file-name (ivy-state-directory ivy-last)))
        (goto-char (point-min))
        (forward-line (1- (string-to-number line-number)))
        (re-search-forward (ivy--regex ivy-text t) (line-end-position) t)
        (run-hooks 'counsel-grep-post-action-hook)
        (selected-window))))))

;;;###autoload
(defun nasy/ivy-confirm-delete-file (x)
  (dired-delete-file x 'confirm-each-subdirectory))


;;
;;; File searching

;;;###autoload
(defun nasy/ivy/projectile-find-file ()
  "A more sensible `counsel-projectile-find-file', which will revert to
`counsel-find-file' if invoked from $HOME, `counsel-file-jump' if invoked from a
non-project, `projectile-find-file' if in a big project (more than
`ivy-sort-max-size' files), or `counsel-projectile-find-file' otherwise.
The point of this is to avoid Emacs locking up indexing massive file trees."
  (interactive)
  ;; Spoof the command so that ivy/counsel will display the (well fleshed-out)
  ;; actions list for `counsel-find-file' on C-o. The actions list for the other
  ;; commands aren't as well configured or are empty.
  (let ((this-command 'counsel-find-file))
    (call-interactively
     (cond ((or (file-equal-p default-directory "~")
              (when-let (proot (nasy/project-root))
                (file-equal-p proot "~")))
            #'counsel-find-file)

         ((nasy/project-p)
          (let ((files (projectile-current-project-files)))
            (if (<= (length files) ivy-sort-max-size)
                #'counsel-projectile-find-file
              #'projectile-find-file)))

         (#'counsel-file-jump)))))

;;;###autoload
(cl-defun nasy/ivy-file-search (&key query in all-files (recursive t) prompt args)
  "Conduct a file search using ripgrep.
:query STRING
  Determines the initial input to search for.
:in PATH
  Sets what directory to base the search out of. Defaults to the current
  project's root.
:recursive BOOL
  Whether or not to search files recursively from the base directory."
  (declare (indent defun))
  (unless (executable-find "rg")
    (user-error "Couldn't find ripgrep in your PATH"))
  (require 'counsel)
  (let* ((this-command 'counsel-rg)
         (project-root (or (nasy/project-root) default-directory))
         (directory (or in project-root))
         (args (concat (if all-files " -uu")
                       (unless recursive " --maxdepth 1")
                       " "
                       (mapconcat #'shell-quote-argument args " "))))
    (setq deactivate-mark t)
    (counsel-rg
     (or query
       (when (nasy/region-active-p)
         (replace-regexp-in-string
          "[! |]" (lambda (substr)
                    (cond ((and (string= substr " ")
                              (not *ivy-fuzzy*))
                           "  ")
                          ((string= substr "|")
                           "\\\\\\\\|")
                          ((concat "\\\\" substr))))
          (rxt-quote-pcre (nasy/thing-at-point-or-region)))))
     directory args
     (or prompt
       (format "rg%s [%s]: "
               args
               (cond ((equal directory default-directory)
                      "./")
                     ((equal directory project-root)
                      (projectile-project-name))
                     ((file-relative-name directory project-root))))))))

;;;###autoload
(defun nasy/ivy/project-search (&optional arg initial-query directory)
  "Performs a live project search from the project root using ripgrep.
If ARG (universal argument), include all files, even hidden or compressed ones,
in the search."
  (interactive "P")
  (nasy/ivy-file-search :query initial-query :in directory :all-files arg))

;;;###autoload
(defun nasy/ivy/project-search-from-cwd (&optional arg initial-query)
  "Performs a project search recursively from the current directory.
If ARG (universal argument), include all files, even hidden or compressed ones."
  (interactive "P")
  (nasy/ivy/project-search arg initial-query default-directory))


;;
;;; Wrappers around `counsel-compile'

;;;###autoload
(defun nasy/ivy/compile ()
  "Execute a compile command from the current buffer's directory."
  (interactive)
  (counsel-compile default-directory))

;;;###autoload
(defun nasy/ivy/project-compile ()
  "Execute a compile command from the current project's root."
  (interactive)
  (counsel-compile (projectile-project-root)))

;;;###autoload
(defun nasy/ivy/git-grep-other-window-action ()
  "Open the current counsel-{ag,rg,git-grep} candidate in other-window."
  (interactive)
  (ivy-set-action #'nasy/ivy-git-grep-other-window-action)
  (setq ivy-exit 'done)
  (exit-minibuffer))
Config
(defvar nasy/ivy-buffer-preview 'everything
  "If non-nil, preview buffers while switching, à la `counsel-switch-buffer'.
When nil, don't preview anything.
When non-nil, preview non-virtual buffers.
When 'everything, also preview virtual buffers")

(defvar nasy/ivy-buffer-unreal-face 'font-lock-comment-face
  "The face for unreal buffers in `ivy-switch-to-buffer'.")

(defvar nasy/ivy-edit-functions nil
  "A plist mapping ivy/counsel commands to commands that generate an editable
results buffer.")
  • ivy
    (leaf ivy
      :hook after-init-hook
      :init
      (let ((standard-search-fn
             (if *ivy-prescient*
                 #'nasy/ivy-prescient-non-fuzzy
               #'ivy--regex-plus))
            (alt-search-fn
             (if *ivy-fuzzy*
                 #'ivy--regex-fuzzy
               ;; Ignore order for non-fuzzy searches by default
               #'ivy--regex-ignore-order)))
        (gsetq ivy-re-builders-alist
               `((counsel-rg     . ,standard-search-fn)
                 (swiper         . ,standard-search-fn)
                 (swiper-isearch . ,standard-search-fn)
                 (t . ,alt-search-fn))
               ivy-more-chars-alist
               '((counsel-rg . 1)
                 (counsel-search . 2)
                 (t . 3))))
      :custom
      ((ivy-wrap                         . t)
       (ivy-auto-shrink-minibuffer-alist . '((t . t)))
       (ivy-height                       . 15)
       (ivy-fixed-height-minibuffer      . nil)
       (projectile-completion-system     . 'ivy)
       ;; disable magic slash on non-match
       (ivy-magic-slash-non-match-action . nil)
       ;; don't show recent files in switch-buffer
       (ivy-use-virtual-buffers          . nil)
       ;; ...but if that ever changes, show their full path
       (ivy-virtual-abbreviate           . 'full)
       ;; don't quit minibuffer on delete-error
       (ivy-on-del-error-function        . #'ignore)
       ;; enable ability to select prompt (alternative to `ivy-immediate-done')
       (ivy-use-selectable-prompt        . t))
      :bind
      ([remap switch-to-buffer]               . nasy/ivy/switch-buffer)
      ([remap switch-to-buffer-other-window]  . nasy/ivy/switch-buffer-other-window)
      ([remap persp-switch-to-buffer]         . nasy/ivy/switch-workspace-buffer)
      (:ivy-mode-map
       ([remap switch-to-buffer]              . nasy/ivy/switch-buffer)
       ([remap switch-to-buffer-other-window] . nasy/ivy/switch-buffer-other-window)
       ([remap persp-switch-to-buffer]        . nasy/ivy/switch-workspace-buffer))
      (:ivy-minibuffer-map
       ("C-c C-e"                         . nasy/ivy-woccur)
       ([remap nasy/delete-backward-word] . ivy-backward-kill-word))
      :config
      ;; Highlight each ivy candidate including the following newline, so that it
      ;; extends to the right edge of the window
      (setf (alist-get 't ivy-format-functions-alist)
            #'ivy-format-function-line)
    
      ;; Integrate `ivy' with `better-jumper'; ensure a jump point is registered
      ;; before jumping to new locations with ivy
      ;; (setf (alist-get 't ivy-hooks-alist)
      ;;       (lambda ()
      ;;         (with-ivy-window
      ;;           (setq nasy/ivy--origin (point-marker)))))
    
      ;; (add-hook 'minibuffer-exit-hook
      ;;   (defun nasy/ivy--set-jump-point-maybe-h ()
      ;;     (and (markerp (bound-and-true-p nasy/ivy--origin))
      ;;          (not (equal (ignore-errors (with-ivy-window (point-marker)))
      ;;                      nasy/ivy--origin))
      ;;          (with-current-buffer (marker-buffer nasy/ivy--origin)
      ;;            (better-jumper-set-jump nasy/ivy--origin)))
      ;;     (setq nasy/ivy--origin nil)))
    
      (after-x 'yasnippet
        (add-hook 'yas-prompt-functions #'nasy/ivy-yas-prompt)))
    
  • ivy-xref
    (leaf ivy-xref
      :custom (xref-show-xrefs-function . #'ivy-xref-show-xrefs))
    
  • counsel
    (leaf counsel
      :custom
      (counsel-find-file-at-point         . t)
      ;; Don't use ^ as initial input. Set this here because `counsel' defines more
      ;; of its own, on top of the defaults.
      (ivy-initial-inputs-alist           . nil)
      ;; helpful
      (counsel-describe-function-function . #'helpful-callable)
      (counsel-describe-variable-function . #'helpful-variable)
      :bind
      (([remap apropos]                    . counsel-apropos)
       ([remap bookmark-jump]              . counsel-bookmark)
       ([remap compile]                    . nasy/ivy/compile)
       ([remap describe-bindings]          . counsel-descbinds)
       ([remap describe-face]              . counsel-faces)
       ([remap describe-function]          . counsel-describe-function)
       ([remap describe-variable]          . counsel-describe-variable)
       ([remap execute-extended-command]   . counsel-M-x)
       ([remap find-file]                  . counsel-find-file)
       ([remap find-library]               . counsel-find-library)
       ([remap imenu]                      . counsel-imenu)
       ([remap info-lookup-symbol]         . counsel-info-lookup-symbol)
       ([remap load-theme]                 . counsel-load-theme)
       ([remap locate]                     . counsel-locate)
       ([remap org-set-tags-command]       . counsel-org-tag)
       ([remap projectile-compile-project] . nasy/ivy/project-compile)
       ([remap recentf-open-files]         . counsel-recentf)
       ([remap set-variable]               . counsel-set-variable)
       ([remap swiper]                     . counsel-grep-or-swiper)
       ([remap unicode-chars-list-chars]   . counsel-unicode-char)
       ([remap yank-pop]                   . counsel-yank-pop))
      (:counsel-find-file-map
       ("<left>"  . counsel-up-directory)
       ("<right>" . counsel-down-directory))
      :config
      ;; (set-popup-rule! "^\\*ivy-occur" :size 0.35 :ttl 0 :quit nil)
    
      ;; HACK Fix an issue where `counsel-projectile-find-file-action' would try to
      ;;      open a candidate in an occur buffer relative to the wrong buffer,
      ;;      causing it to fail to find the file we want.
      ;; (defadvice! nasy/ivy--run-from-ivy-directory-a (orig-fn &rest args)
      ;;   :around #'counsel-projectile-find-file-action
      ;;   (let ((default-directory (ivy-state-directory ivy-last)))
      ;;     (apply orig-fn args)))
    
      ;; Record in jumplist when opening files via counsel-{ag,rg,pt,git-grep}
      ;; (add-hook 'counsel-grep-post-action-hook #'better-jumper-set-jump)
      (ivy-add-actions
       'counsel-rg ; also applies to `counsel-rg'
       '(("O" nasy/ivy-git-grep-other-window-action "open in other window")))
    
      ;; Make `counsel-compile' projectile-aware (if you prefer it over
      ;; `nasy/ivy/compile' and `nasy/ivy/project-compile')
      (add-to-list 'counsel-compile-root-functions #'projectile-project-root)
      (after-x 'savehist
        ;; Persist `counsel-compile' history
        (add-to-list 'savehist-additional-variables 'counsel-compile-history))
    
      ;; `counsel-imenu' -- no sorting for imenu. Sort it by appearance in page.
      (add-to-list 'ivy-sort-functions-alist '(counsel-imenu))
    
      ;; `counsel-locate'
      (when *is-a-mac*
        ;; Use spotlight on mac by default since it doesn't need any additional setup
        (setq counsel-locate-cmd #'counsel-locate-cmd-mdfind))
    
      ;; `swiper'
      ;; Don't mess with font-locking on the dashboard; it causes breakages
      ;; (add-to-list 'swiper-font-lock-exclude #'+doom-dashboard-mode)
    
      ;; `counsel-find-file'
      (setq counsel-find-file-ignore-regexp "\\(?:^[#.]\\)\\|\\(?:[#~]$\\)\\|\\(?:^Icon?\\)")
      (dolist (fn '(counsel-rg counsel-find-file))
        (ivy-add-actions
         fn '(("p" (lambda (path) (with-ivy-window (insert (file-relative-name path default-directory))))
               "insert relative path")
              ("P" (lambda (path) (with-ivy-window (insert path)))
               "insert absolute path")
              ("l" (lambda (path) (with-ivy-window (insert (format "[[./%s]]" (file-relative-name path default-directory)))))
               "insert relative org-link")
              ("L" (lambda (path) (with-ivy-window (insert (format "[[%s]]" path))))
               "Insert absolute org-link"))))
    
      (ivy-add-actions 'counsel-file-jump (plist-get ivy--actions-list 'counsel-find-file))
    
      ;; `counsel-search': use normal page for displaying results, so that we see
      ;; custom ddg themes (if one is set).
      (setf (nth 1 (alist-get 'ddg counsel-search-engines-alist))
            "https://duckduckgo.com/?q=")
      ;; REVIEW Move this somewhere else and perhaps generalize this so both
      ;;        ivy/helm users can enjoy it.
      (defun nasy/ivy--counsel-file-jump-use-fd-rg-a(args)
        "Change `counsel-file-jump' to use fd or ripgrep, if they are available."
        (cl-destructuring-bind (find-program . args)
            (cond ((when-let (fd (executable-find (or doom-projectile-fd-binary "fd")))
                     (append (list fd
                                   "--color=never" "-E" ".git"
                                   "--type" "file" "--type" "symlink" "--follow")
                             (if IS-WINDOWS '("--path-separator=/")))))
                  ((executable-find "rg")
                   (append (list "rg" "--files" "--follow" "--color=never" "--hidden" "--no-messages")
                           (cl-loop for dir in projectile-globally-ignored-directories
                                    collect "--glob"
                                    collect (concat "!" dir))
                           (if IS-WINDOWS (list "--path-separator" "/"))))
                  ((cons find-program args)))
          (unless (listp args)
            (user-error "`counsel-file-jump-args' is a list now, please customize accordingly."))
          (counsel--call
           (cons find-program args)
           (lambda ()
             (goto-char (point-min))
             (let (files)
               (while (< (point) (point-max))
                 (push (buffer-substring (line-beginning-position) (line-end-position))
                       files)
                 (forward-line 1))
               (nreverse files))))))
      :advice (:override counsel--find-return-list nasy/ivy--counsel-file-jump-use-fd-rg-a))
    
  • counsel-projectile
    (leaf counsel-projectile
      :bind
      (([remap projectile-find-file]        . nasy/ivy/projectile-find-file)
       ([remap projectile-find-dir]         . counsel-projectile-find-dir)
       ([remap projectile-switch-to-buffer] . counsel-projectile-switch-to-buffer)
       ([remap projectile-grep]             . counsel-projectile-grep)
       ([remap projectile-ag]               . counsel-projectile-ag)
       ([remap projectile-switch-project]   . counsel-projectile-switch-project))
      :config
      ;; A more sensible `counsel-projectile-find-file' that reverts to
      ;; `counsel-find-file' if invoked from $HOME, `counsel-file-jump' if invoked
      ;; from a non-project, `projectile-find-file' if in a big project (more than
      ;; `ivy-sort-max-size' files), or `counsel-projectile-find-file' otherwise.
      (setf (alist-get 'projectile-find-file counsel-projectile-key-bindings)
            #'nasy/ivy/projectile-find-file)
    
      (after-x 'prescient
        (gsetq counsel-projectile-sort-files t)))
    
  • ivy-prescient
    (leaf ivy-prescient
      :hook ivy-mode-hook
      :mode-hook (prescient-persist-mode 1)
      :custom (ivy-prescient-retain-classic-highlighting . t)
      :config
      (defun nasy/ivy-prescient-non-fuzzy (str)
        (let ((prescient-filter-method '(literal regexp)))
          (ivy-prescient-re-builder str))))
    
    
  • icons and rich
    (leaf all-the-icons-ivy-rich
      :defvar nasy/all-the-icons-ivy-rich-reload-p
      :custom
      (all-the-icons-ivy-rich-icon-size . 0.7)
      :init
      (all-the-icons-ivy-rich-mode 1)
      (setq nasy/all-the-icons-ivy-rich-reload-p nil)
      (defun nasy/ivy-rich-reload ()
        (if (and all-the-icons-ivy-rich-mode
                nasy/all-the-icons-ivy-rich-reload-p)
            (advice-remove #'counsel-M-x #'nasy/ivy-rich-reload)
          (all-the-icons-ivy-rich-reload)
          (setq nasy/all-the-icons-ivy-rich-reload-p t)))
      (defun nasy/all-the-icons-ivy-rich-align-icons ()
        "Set tab size to 1, to insert tabs as delimiters."
        (setq-local tab-width 2))
      :advice
      (:before counsel-M-x nasy/ivy-rich-reload)
      (:override all-the-icons-ivy-rich-align-icons nasy/all-the-icons-ivy-rich-align-icons))
    
    (leaf ivy-rich
      :init (ivy-rich-mode 1))
    
List Unicode Display   convenience

Provides a command which searches for unicode characters by name, and displays a list of matching characters with their names in a buffer.

https://github.com/purcell/list-unicode-display

(leaf list-unicode-display
  :doc "Search for and list unicode characters in Emacs.

`list-unicode-display'"
  :url "https://github.com/purcell/list-unicode-display"
  :tag "convenience")
mmm-mode   convenience faces languages tools

MMM Mode is a minor mode for Emacs that allows Multiple Major Modes to coexist in one buffer.

https://github.com/purcell/mmm-mode

(leaf mmm-auto
  :doc "MMM Mode is a minor mode for Emacs that allows Multiple Major Modes
to coexist in one buffer."
  :url "https://github.com/purcell/mmm-mode"
  :tag "convenience" "faces" "languages" "tools"
  :custom
  (mmm-global-mode
   . 'buffers-with-submode-classes)
  (mmm-submode-decoration-level
   . 2))
Multiple Cursors   cursors editing

Multiple cursors for Emacs.

https://github.com/magnars/multiple-cursors.el

(leaf multiple-cursors
  :doc "Multiple cursors for Emacs."
  :url "https://github.com/magnars/multiple-cursors.el"
  :tag "editing" "cursors"
  :bind
  (("C-<"     . mc/mark-previous-like-this)
   ("C->"     . mc/mark-next-like-this)
   ("C-+"     . mc/mark-next-like-this)
   ("C-c C-<" . mc/mark-all-like-this)

   ("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)))
Paper Break Lines   convenience faces

This Emacs library provides a global mode which displays ugly form feed characters as tidy horizontal rules.

https://github.com/purcell/page-break-lines

(leaf page-break-lines
  :doc "Emacs: display ugly ^L page breaks as tidy horizontal lines"
  :url "https://github.com/purcell/page-break-lines"
  :tag "convenience" "faces"
  :hook ((after-init-hook . global-page-break-lines-mode))
  :defer-config
  (when (fboundp 'diminish)
    (diminish 'page-break-lines-mode)))
Parens   faces languages
(leaf paren
  :hook (after-init-hook . show-paren-mode))
Rainbow Delimiters   convenience faces lisp tools

rainbow-delimiters is a "rainbow parentheses"-like mode which highlights delimiters such as parentheses, brackets or braces according to their depth. Each successive level is highlighted in a different color. This makes it easy to spot matching delimiters, orient yourself in the code, and tell which statements are at a given depth.

https://github.com/Fanael/rainbow-delimiters

(leaf rainbow-delimiters
  :doc "Emacs rainbow delimiters mode"
  :url "https://github.com/Fanael/rainbow-delimiters"
  :tag "convenience" "faces" "lisp" "tools"
  :hook prog-mode-hook org-src-mode-hook)
Smartparens   abbrev convenience editing

Minor mode for Emacs that deals with parens pairs and tries to be smart about it.

https://github.com/Fuco1/smartparens

(leaf smartparens-config
  :doc "Minor mode for Emacs that deals with parens pairs and tries to be smart about it."
  :url "https://github.com/Fuco1/smartparens"
  :tag "abbrev" "convenience" "editing"
  :hook (after-init-hook . smartparens-global-mode)
  :custom (sp-hybrid-kill-entire-symbol . nil))
PDF Tools   files multimedia

PDF Tools is, among other things, a replacement of DocView for PDF files.

https://github.com/politza/pdf-tools

(leaf pdf-tools
  :doc "Emacs support library for PDF files."
  :url "https://github.com/politza/pdf-tools"
  :tag "files" "multimedia"
  :bind (: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))
  :custom (pdf-view-display-size . 'fit-width))
Pretty Font
(leaf pretty-font
  :when (fboundp 'mac-auto-operator-composition-mode)
  :preface
  ;; 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
  :config
  (defun pretty-fonts-set-fontsets (CODE-FONT-ALIST)
    "Utility to associate many unicode points with specified `CODE-FONT-ALIST'."
    (--each CODE-FONT-ALIST
      (-let (((font . codes) it))
        (--each codes
          (set-fontset-font nil `(,it . ,it) font)
          (set-fontset-font t `(,it . ,it) font)))))

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

                          ("pi"     . #x03c0)  ;; π

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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


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

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

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

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

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

Projectile is a project interaction library for Emacs. Its goal is to provide a nice set of features operating on a project level without introducing external dependencies (when feasible). For instance - finding project files has a portable implementation written in pure Emacs Lisp without the use of GNU find (but for performance sake an indexing mechanism backed by external commands exists as well).

https://github.com/bbatsov/projectile

(leaf projectile
  :doc "Projectile is a project interaction library for Emacs."
  :url "https://github.com/bbatsov/projectile"
  :tag "project" "convenience"
  :bind ([remap find-tag] . projectile-find-tag)
  :hook after-init-hook
  :custom
  (projectile-indexing-method      . 'hybrid)
  (projectile-require-project-root . 'prompt)
  :config
  (gsetq projectile-project-root-files-top-down-recurring
         (append '("compile_commands.json"
                   ".cquery")
                 projectile-project-root-files-top-down-recurring)))
Prescient   extensions

☄️ Simple but effective sorting and filtering for Emacs.

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

(leaf prescient
  :doc "☄️ Simple but effective sorting and filtering for Emacs."
  :url "https://github.com/raxod502/prescient.el"
  :tag "extensions"
  :hook ((after-init-hook . prescient-persist-mode)))
Quick Peek   convenience docs help tools

An inline pop-up library for Emacs Lisp.

https://github.com/cpitclaudel/quick-peek

(leaf quick-peek
  :doc "An inline pop-up library for Emacs Lisp."
  :url "https://github.com/cpitclaudel/quick-peek"
  :tag "convenience" "docs" "help" "tools"
  :custom-face
  (quick-peek-border-face  . '((t (:background "#75b79e" :height 0.1))))
  (quick-peek-padding-face . '((t (:height 0.1)))))
Recentf   files

Recentf is a minor mode that builds a list of recently opened files.

https://www.emacswiki.org/emacs/RecentFiles

(leaf recentf
  :doc "Recentf is a minor mode that builds a list of recently opened files."
  :url "https://www.emacswiki.org/emacs/RecentFiles"
  :tag "files"
  :hook after-init-hook
  :custom
  (recentf-filename-handlers
   . '(;; Text properties inflate the size of recentf's files, and there is
       ;; no purpose in persisting them, so we strip them out.
       substring-no-properties
       ;; Resolve symlinks of local files. Otherwise we get duplicate
       ;; entries opening symlinks.
       nasy--recent-file-truename
       ;; Replace $HOME with ~, which is more portable, and reduces how much
       ;; horizontal space the recentf listing uses to list recent files.
       abbreviate-file-name))
  (recentf-max-saved-items . 100)
  (recentf-exclude         . '("/tmp/" "/ssh:"))
  :config
  (defun nasy--recent-file-truename (file)
    (if (or (file-remote-p file nil t)
            (not (file-remote-p file)))
        (file-truename file)
      file))

  (add-to-list 'recentf-exclude no-littering-var-directory)
  (add-to-list 'recentf-exclude no-littering-etc-directory))
Snails

A modern, easy-to-expand fuzzy search framework

https://github.com/manateelazycat/snails

Not work now.

Subword   builtin
(leaf subword
  :tag "builtin"
  :hook prog-mode-hook)
Switch-Window

Offer a visual way to choose a window to switch to.

https://github.com/dimitri/switch-window

(leaf switch-window
  :doc "Offer a *visual* way to choose a window to switch to."
  :url "https://github.com/dimitri/switch-window"
  :bind
  ("C-x o" . switch-window)
  ("C-x 1" . toggle-delete-other-windows)
  ("C-x 2" . split-window-v)
  ("C-x 3" . split-window-h)
  ("C-x |" . split-window-horizontally-instead)
  ("C-x _" . split-window-vertically-instead)
  ("C-x x" . nasy/split-window)
  ("M-o"   . transient-dwim--switch-window)
  :custom
  (switch-window-shortcut-style . 'alphabet)
  (switch-window-timeout        . nil)
  :transient
  (transient-dwim--switch-window
   ()
   "Transient-dwim for `switch-window'."
   [["Switch Window"
     ("o" "Switch Window" switch-window)]])
  :config
  ;; When splitting window, show (other-buffer) in the new window
  (defun split-window-func-with-other-buffer (split-function)
    "Split window with `SPLIT-FUNCTION'."
    (lambda (&optional arg)
      "Split this window and switch to the new window unless ARG is provided."
      (interactive "P")
      (funcall split-function)
      (let ((target-window (next-window)))
        (set-window-buffer target-window (other-buffer))
        (unless arg
          (select-window target-window)))))

  (defun split-window-v ()
    (split-window-func-with-other-buffer 'split-window-vertically))

  (defun split-window-h ()
    (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)))

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

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

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

Highlight symbols with overlays while providing a keymap for various operations about highlighted symbols. It was originally inspired by the package highlight-symbol. The fundamental difference is that in symbol-overlay every symbol is highlighted by the Emacs built-in function overlay-put rather than the font-lock mechanism used in highlight-symbol.

https://github.com/wolray/symbol-overlay

(leaf symbol-overlay
  :doc "Highlight symbols with keymap-enabled overlays."
  :url "https://github.com/wolray/symbol-overlay"
  :tag "faces" "matching"
  :bind (("M-i"  . symbol-overlay-put)
         ("M-n"  . symbol-overlay-switch-forward)
         ("M-p"  . symbol-overlay-switch-backward)
         ("<f8>" . symbol-overlay-remove-all)
         ("<f7>" . symbol-overlay-mode)))
Treemacs   convenience files

Treemacs is a file and project explorer similar to NeoTree or vim’s NerdTree, but largely inspired by the Project Explorer in Eclipse. It shows the file system outlines of your projects in a simple tree layout allowing quick navigation and exploration, while also possessing basic file management utilities.

https://github.com/Alexander-Miller/treemacs

(leaf treemacs
  :doc "A tree layout file explorer for Emacs"
  :url "https://github.com/Alexander-Miller/treemacs"
  :tag "convenience" "files"
  :init
  (after-x 'winum
    (define-key winum-keymap (kbd "M-0") #'treemacs-select-window))
  :defer-config
  (gsetq treemacs-collapse-dirs                 (if treemacs-python-executable 3 0)
         treemacs-deferred-git-apply-delay      0.5
         treemacs-directory-name-transformer    #'identity
         treemacs-display-in-side-window        t
         treemacs-eldoc-display                 t
         treemacs-file-event-delay              5000
         treemacs-file-extension-regex          treemacs-last-period-regex-value
         treemacs-file-follow-delay             0.2
         treemacs-file-name-transformer         #'identity
         treemacs-follow-after-init             t
         treemacs-git-command-pipe              ""
         treemacs-goto-tag-strategy             'refetch-index
         treemacs-indentation                   2
         treemacs-indentation-string            " "
         treemacs-is-never-other-window         nil
         treemacs-max-git-entries               5000
         treemacs-missing-project-action        'ask
         treemacs-move-forward-on-expand        t
         treemacs-no-png-images                 nil
         treemacs-no-delete-other-windows       t
         treemacs-project-follow-cleanup        nil
         treemacs-persist-file                  (no-littering-expand-var-file-name "treemacs-persist")
         treemacs-position                      'left
         treemacs-recenter-distance             0.1
         treemacs-recenter-after-file-follow    nil
         treemacs-recenter-after-tag-follow     nil
         treemacs-recenter-after-project-jump   'always
         treemacs-recenter-after-project-expand 'on-distance
         treemacs-show-cursor                   nil
         treemacs-show-hidden-files             t
         treemacs-silent-filewatch              nil
         treemacs-silent-refresh                nil
         treemacs-sorting                       'alphabetic-desc
         treemacs-space-between-root-nodes      t
         treemacs-tag-follow-cleanup            t
         treemacs-tag-follow-delay              1.5
         treemacs-user-mode-line-format         nil
         treemacs-user-header-line-format       nil
         treemacs-width                         35)

  ;; The default width and height of the icons is 22 pixels. If you are
  ;; using a Hi-DPI display, uncomment this to double the icon size.
  ;; (treemacs-resize-icons 44)
  (treemacs-follow-mode t)
  (treemacs-filewatch-mode t)
  (treemacs-fringe-indicator-mode t)
  (pcase (cons (not (null (executable-find "git")))
               (not (null treemacs-python-executable)))
    (`(t . t)
     (treemacs-git-mode 'deferred))
    (`(t . _)
     (treemacs-git-mode 'simple))))


(leaf treemacs-icons-dired
  :after treemacs dired
  :config (treemacs-icons-dired-mode))

(leaf treemacs-magit
  :after treemacs magit)

(leaf treemacs-projectile
  :after treemacs projectile)
Tree Sitter   languages parsers tools

emacs-tree-sitter is an Emacs binding for tree-sitter, an incremental parsing system.

https://ubolonton.github.io/emacs-tree-sitter/

(leaf tree-sitter
  :doc "emacs-tree-sitter is an Emacs binding for tree-sitter, an incremental parsing
system."
  :url "https://github.com/ubolonton/emacs-tree-sitter"
  :tag "languagues" "parsers" "tools"
  :hook (agda-mode-hook
         shell-mode-hook
         c-mode-hook
         c++-mode-hook
         css-mode-hook
         haskell-mode-hook
         html-mode-hook
         js-mode-hook
         js2-mode-hook
         son-mode-hook
         python-mode-hook
         ruby-mode-hook
         rust-mode-hook
         typescript-mode-hook)
  :config
  (require 'tree-sitter-langs)
  (add-to-list 'tree-sitter-major-mode-language-alist '(mhtml-mode . html)))

(leaf tree-sitter-hl
  :hook tree-sitter-after-on-hook)
Undo/Redo   editing
(leaf undo/redo
  :doc "Undo/redo for emacs"
  :tag "editing")
Point History

Show the history of points you visited before.

https://github.com/blue0513/point-history

(leaf point-history
  :doc "Show the history of points you visited before."
  :url "https://github.com/blue0513/point-history"
  :tag "editing"
  :hook after-init-hook
  :bind (("C-c C-/" . point-history-show))
  :custom (point-history-ignore-buffer . "^ \\*Minibuf\\|^ \\*point-history-show*"))
Undo Propose   convenience files undo redo history

Navigate the emacs undo history by staging undo's in a temporary buffer.

https://github.com/jackkamm/undo-propose-el

(leaf undo-propose
  :doc "Navigate the emacs undo history by staging undo's in a temporary buffer."
  :url "https://github.com/jackkamm/undo-propose-el"
  :tag "convenience" "files" "undo" "redo" "history"
  :bind (("C-c u" . undo-propose))
  :config
  (undo-propose-wrap undo)
  (undo-propose-wrap redo))
Uniquify   builtin files
(leaf uniquify
  :tag "builtin" "files"
  :custom
  (uniquify-buffer-name-style   . 'reverse)
  (uniquify-separator           . " • ")
  (uniquify-after-kill-buffer-p . t)
  (uniquify-ignore-buffers-re   . "^\\*"))
Version Control   git tools vc
(leaf version-control
  :tag "git" "tools" "vc")
abridge-diff   diffs magit tools

A simple Emacs package for abridging refined diff hunks (for example in magit). Why abridge a diff hunk? Most diffs are line based. If you are working on files with very long lines, for example LaTeX files, or text files with full paragraphs per line (often using visual-line-mode), line-based diffs can be very challenging to read, even with "hunk refining" enabled (highlighting the words which changed).

https://github.com/jdtsmith/abridge-diff

(leaf abridge-diff
  :doc "Emacs package for refining diff hunks with very long lines (as in LaTeX files)."
  :url "https://github.com/jdtsmith/abridge-diff"
  :tag "diffs" "magit" "tools"
  :after magit
  :init (abridge-diff-mode 1))
Diff-hl (only for dired)

Emacs package for highlighting uncommitted changes

https://github.com/dgutov/diff-hl

(leaf diff-hl
  :doc "Emacs package for highlighting uncommitted changes"
  :url "https://github.com/dgutov/diff-hl"
  :tag "vc" "diff"
  :hook ((dired-mode-hook         . diff-hl-dired-mode)
         (magit-pre-refresh-hook  . diff-hl-magit-pre-refresh)
         (magit-post-refresh-hook . diff-hl-magit-post-refresh)))
Forge   git tools vc

Work with Git forges from the comfort of Magit.

https://github.com/magit/forge

(leaf forge
  :doc "Work with Git forges from the comfort of Magit."
  :url "https://github.com/magit/forge"
  :tag "git" "tools" "vc")
Git Gutter
(leaf git-gutter
  :hook (after-init . global-git-gutter-mode)
  :custom ((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   . "✘"))
  :bind (("C-x v =" . git-gutter:popup-hunk)
         ("C-x p"   . git-gutter:previous-hunk)
         ("C-x n"   . git-gutter:next-hunk)))
Git Messenger   convenience vc

git-messenger.el provides function that popup commit message at current line.

https://github.com/emacsorphanage/git-messenger

(leaf git-messenger
  :doc "git-messenger.el provides function that popup commit message at current line."
  :url "https://github.com/emacsorphanage/git-messenger"
  :tag "convenience" "vc"
  :custom (git-messenger:show-detail . t)
  :bind (:vc-prefix-map
         ("p" . git-messenger:popup-message)))
Magit   git tools vc

Magit is an interface to the version control system Git, implemented as an Emacs package. Magit aspires to be a complete Git porcelain. While we cannot (yet) claim that Magit wraps and improves upon each and every Git command, it is complete enough to allow even experienced Git users to perform almost all of their daily version control tasks directly from within Emacs. While many fine Git clients exist, only Magit and Git itself deserve to be called porcelains.

https://github.com/magit/magit

(leaf magit
  :doc "It's Magit! A Git porcelain inside Emacs."
  :url "https://github.com/magit/magit"
  :tag "git" "tools" "vc"
  :commands magit-status
  :hook ((magit-popup-mode-hook . no-trailing-whitespace))
  :custom ((magit-diff-refine-hunk . t)
           (vc-handled-backends    . nil))
  :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)
         (:magit-status-mode-map
          ("C-M-<up>"  . magit-section-up))
         (:vc-prefix-map
          ("f"         . vc-git-grep))))
Magit Org Todos   magit orgmode tools

Get `todo.org` into your magit status.

https://github.com/danielma/magit-org-todos.el

(leaf magit-org-todos
  :doc "Get `todo.org` into your magit status"
  :url "https://github.com/danielma/magit-org-todos.el"
  :tag "magit" "orgmode" "tools"
  :after magit
  :require t
  :config (magit-org-todos-autoinsert))
Magit Todos   magit vc

Show source files' TODOs (and FIXMEs, etc) in Magit status buffer.

https://github.com/alphapapa/magit-todos

(leaf magit-todos
  :doc "Show source files' TODOs (and FIXMEs, etc) in Magit status buffer."
  :url "https://github.com/alphapapa/magit-todos"
  :tag "magit" "vc"
  :custom (magit-todos-exclude-globs . '("*.map")))
View Large File

Emacs minor mode that allows viewing, editing, searching and comparing large files in batches, trading memory for processor time.

https://github.com/m00natic/vlfi

(leaf vlf
  :doc "View Large Files in Emacs"
  :url "https://github.com/m00natic/vlfi"
  :tag "files" "large files" "utilities"
  :commands ffap-vlf
  :init
  (defun ffap-vlf ()
    "Find file at point with VLF."
    (interactive)
    (let ((file (ffap-file-at-point)))
      (unless (file-exists-p file)
        (error "File does not exist: %s" file))
      (vlf file))))
Which Function   builtin
(leaf which-func
  :tag "builtin"
  :hook after-init-hook)
Which Key   help

Emacs package that displays available keybindings in popup.

https://github.com/justbur/emacs-which-key

(leaf which-key
  :doc "Emacs package that displays available keybindings in popup."
  :url "https://github.com/justbur/emacs-which-key"
  :tag "help"
  :custom (which-key-allow-imprecise-window-fit . nil)
  :hook 'after-init-hook)
Whitespace   convenience data wp

Visualize blanks (TAB, (HARD) SPACE and NEWLINE).

https://www.emacswiki.org/emacs/WhiteSpace

In Emacs, intelligently call whitespace-cleanup on save.

https://github.com/purcell/whitespace-cleanup-mode

(leaf whitespace
  :tag "data" "wp"
  :init
  (defun no-trailing-whitespace ()
    "Turn off display of trailing whitespace in this buffer."
    (setq show-trailing-whitespace nil))
  :hook
  ;; But don't show trailing whitespace in SQLi, inf-ruby etc.
  ((artist-mode-hook
    picture-mode-hook
    special-mode-hook
    Info-mode-hook
    eww-mode-hook
    term-mode-hook
    vterm-mode-hook
    comint-mode-hook
    compilation-mode-hook
    twittering-mode-hook
    minibuffer-setup-hook
    fundamental-mode) . no-trailing-whitespace))


(leaf whitespace-cleanup-mode
  :doc "In Emacs, intelligently call whitespace-cleanup on save."
  :url "https://github.com/purcell/whitespace-cleanup-mode"
  :tag "convonience"
  :custom
  (whitespace-cleanup-mode-only-if-initially-clean . nil)
  (whitespace-style
   . '(face tabs spaces trailing space-before-tab
            newline indentation empty space-after-tab
            space-mark tab-mark newline-mark))
  :hook ((after-init-hook . global-whitespace-cleanup-mode))
  :bind (("<remap> <just-one-space>" . cycle-spacing)))
Writeroom Mode
(leaf writeroom-mode
  :preface
  (define-minor-mode prose-mode
    "Set up a buffer for prose editing.
This enables or modifies a number of settings so that the
experience of editing prose is a little more like that of a
typical word processor."
    nil " Prose" nil
    (if prose-mode
        (progn
          (when (fboundp 'writeroom-mode)
            (writeroom-mode 1))
          (setq truncate-lines nil)
          (setq word-wrap t)
          (setq cursor-type 'bar)
          (when (eq major-mode 'org)
            (kill-local-variable 'buffer-face-mode-face))
          (buffer-face-mode 1)
          ;;(delete-selection-mode 1)
          (set (make-local-variable 'blink-cursor-interval) 0.6)
          (set (make-local-variable 'show-trailing-whitespace) nil)
          (set (make-local-variable 'line-spacing) 0.2)
          (set (make-local-variable 'electric-pair-mode) nil)
          (ignore-errors (flyspell-mode 1))
          (visual-line-mode 1))
      (kill-local-variable 'truncate-lines)
      (kill-local-variable 'word-wrap)
      (kill-local-variable 'cursor-type)
      (kill-local-variable 'show-trailing-whitespace)
      (kill-local-variable 'line-spacing)
      (kill-local-variable 'electric-pair-mode)
      (buffer-face-mode -1)
      ;; (delete-selection-mode -1)
      (flyspell-mode -1)
      (visual-line-mode -1)
      (when (fboundp 'writeroom-mode)
        (writeroom-mode 0)))))
Yasnipeet   convenience emulation

YASnippet is a template system for Emacs. It allows you to type an abbreviation and automatically expand it into function templates. Bundled language templates include: C, C++, C#, Perl, Python, Ruby, SQL, LaTeX, HTML, CSS and more. The snippet syntax is inspired from TextMate's syntax, you can even import most TextMate templates to YASnippet. Watch a demo on YouTube.

https://github.com/joaotavora/yasnippet

(leaf yasnippet
  :doc "A template system for Emacs"
  :url "https://github.com/joaotavora/yasnippet"
  :tag "convenience" "enmulation"
  :commands (yas-minor-mode)
  :hook (((prog-mode-hook text-mode-hook) . yas-minor-mode))
  :config
  (add-to-list 'yas-snippet-dirs
               (concat user-emacs-directory "extra/snippets"))
  (yas-reload-all))

Tools

(nasy/local-repo tools)
(require 'nasy-tools)

Here is the tools, including buffer, convenience, hyperlink, mac, matching, project, and tools.

Packages

Packages list

  • all-the-icons
  • anzu
  • avy
  • beginend
  • carbon-now-sh
  • Company
    • company-box
    • company-dict
    • company-fix
    • company-math
    • company-prescient
    • company-restclient
    • company-tabnine
  • emojify (when emacs-version less than 27)
  • fill-column
    • Unfill
    • visual-fill-column
  • find-file-in-project
  • grab-mac-link (when is a mac)
  • ibuffer
    • ibuffer-vc
    • all-the-icons-ibuffer
  • imenu-list
  • isearch
  • restclient
    • ob-restclient
    • restclient
  • thingopt
(nasy/s-u-p
  all-the-icons
  anzu
  avy
  beginend
  carbon-now-sh

  ;; company
  company
  (:when *c-box* company-box)
  company-dict
  company-flx
  company-math
  company-prescient
  company-quickhelp
  company-restclient
  company-tabnine

  (:when (version< emacs-version "27") emojify)

  ;; fill column
  unfill
  visual-fill-column

  find-file-in-project
  (:when *is-a-mac* grab-mac-link)
  ;; flycheck
  flycheck
  flycheck-package
  (:when *flycheck-inline* flycheck-inline quick-peek)
  ;; ibuffer
  ibuffer-vc
  all-the-icons-ibuffer

  ob-restclient
  restclient
  thingopt)

Configs

Anzu

anzu.el is an Emacs port of anzu.vim. anzu.el provides a minor mode which displays current match and total matches information in the mode-line in various search modes.

https://github.com/emacsorphanage/anzu

(leaf anzu
  :doc "anzu.el is an Emacs port of anzu.vim."
  :url "https://github.com/emacsorphanage/anzu"
  :hook ((after-init-hook . global-anzu-mode))
  :bind (([remap query-replace]        . anzu-query-replace)
         ([remap query-replace-regexp] . 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\n"
      "r\"\"\"\n"
      "Life's pathetic, have fun (\"▔□▔)/hi~♡ Nasy.\n\n"
      "Excited without bugs::\n\n"
      "    |             *         *\n"
      "    |                  .                .\n"
      "    |           .\n"
      "    |     *                      ,\n"
      "    |                   .\n"
      "    |\n"
      "    |                               *\n"
      "    |          |\\___/|\n"
      "    |          )    -(             .              ·\n"
      "    |         =\\ -   /=\n"
      "    |           )===(       *\n"
      "    |          /   - \\\n"
      "    |          |-    |\n"
      "    |         /   -   \\     0.|.0\n"
      "    |  NASY___\\__( (__/_____(\\=/)__+1s____________\n"
      "    |  ______|____) )______|______|______|______|_\n"
      "    |  ___|______( (____|______|______|______|____\n"
      "    |  ______|____\\_|______|______|______|______|_\n"
      "    |  ___|______|______|______|______|______|____\n"
      "    |  ______|______|______|______|______|______|_\n"
      "    |  ___|______|______|______|______|______|____\n\n"
      "author   : Nasy https://nasy.moe\n"
      "date     : " (format-time-string "%b %e, %Y") "\n"
      "email    : Nasy <[email protected]>" "\n"
      "filename : " (file-name-nondirectory (buffer-file-name)) "\n"
      "project  : " (file-name-nondirectory (directory-file-name (or projectile-project-root default-directory))) "\n"
      "license  : GPL-3.0+\n\n"
      "At pick'd leisure\n"
      "  Which shall be shortly, single I'll resolve you,\n"
      "Which to you shall seem probable, of every\n"
      "  These happen'd accidents\n"
      "                          -- The Tempest\n"
      "\"\"\"\n"))

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

Jump to things in Emacs tree-style.

https://github.com/abo-abo/avy

(leaf avy
  :doc "Jump to things in Emacs tree-style."
  :url "https://github.com/abo-abo/avy"
  :init
  (when *dvorak*
    (gsetq avy-keys '(?a ?o ?e ?u ?i ?d ?h ?t ?n ?s)))
  :bind
  ("C-:"     . avy-goto-char)
  ("C-'"     . avy-goto-char-2)
  ("C-`"     . avy-goto-char-2)
  ("M-g e"   . avy-goto-word-0)
  ("M-g w"   . avy-goto-word-1)
  ("C-~"     . avy-goto-word-1)
  ("C-c C-j" . avy-resume))
Beginend

Emacs package to redefine M-< and M-> for some modes

https://github.com/DamienCassou/beginend

(leaf beginend
  :doc "Emacs package to redefine M-< and M-> for some modes"
  :url "https://github.com/DamienCassou/beginend"
  :hook ((after-init-hook . beginend-global-mode)))
Carbon Now sh

Emacs to carbon.now.sh integration.

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

Try: M-x carbon-now-sh RET

Company

Modular in-buffer completion framework for Emacs.

https://github.com/company-mode/company-mode

Autoloads
(require 'company)
;; Borrow from doom emacs.

;;;###autoload
(defvar nasy/company-backend-alist
  '((text-mode company-dabbrev company-yasnippet company-ispell company-files)
    (prog-mode company-capf company-yasnippet company-files)
    (conf-mode company-capf company-dabbrev-code company-yasnippet company-files))
  "An alist matching modes to company backends. The backends for any mode is
built from this.")


;;;###autoload
(defun nasy/add-company-backend (modes &rest backends)
  "Prepends BACKENDS (in order) to `company-backends' in MODES.

MODES should be one symbol or a list of them, representing major or minor modes.
This will overwrite backends for MODES on consecutive uses.

If the car of BACKENDS is nil, unset the backends for MODES.
Examples:
 (nasy/add-company-backend 'js2-mode
   'company-tide 'company-yasnippet)
 (nasy/add-company-backend 'sh-mode
   '(company-shell :with company-yasnippet))
 (nasy/add-company-backend '(c-mode c++-mode)
   '(:separate company-irony-c-headers company-irony))
 (nasy/add-company-backend 'sh-mode nil)  ; unsets backends for sh-mode"

  (declare (indent defun))
  (dolist (mode (nasy-enlist modes))
    (if (null (car backends))
        (setq nasy/company-backend-alist
              (delq (assq mode nasy/company-backend-alist)
                    nasy/company-backend-alist))
      (setf (alist-get mode nasy/company-backend-alist)
            backends))))


;;;###autoload
(defun nasy/company-backends ()
  (let (backends)
    (let ((mode major-mode)
          (modes (list major-mode)))
      (while (setq mode (get mode 'derived-mode-parent))
        (push mode modes))
      (dolist (mode modes)
        (dolist (backend (append (cdr (assq mode nasy/company-backend-alist))
                                 (default-value 'company-backends)))
          (push backend backends)))
      (delete-dups
       (append (cl-loop for (mode . backends) in nasy/company-backend-alist
                        if (or (eq major-mode mode)  ; major modes
                              (and (boundp mode)
                                 (symbol-value mode))) ; minor modes
                        append backends)
               (nreverse backends))))))


;;;###autoload
(defun nasy/company-init-backends-h ()
  "Set `company-backends' for the current buffer."
  (or (memq major-mode '(fundamental-mode special-mode))
     buffer-read-only
     (nasy/temp-buffer-p (or (buffer-base-buffer) (current-buffer)))
     (setq-local company-backends (nasy/company-backends))))


(put 'nasy/company-init-backends-h 'permanent-local-hook t)


;;;###autoload
(defun nasy/company-complete ()
  "Bring up the completion popup. If only one result, complete it."
  (interactive)
  (require 'company)
  (when (ignore-errors
          (/= (point)
              (cdr (bounds-of-thing-at-point 'symbol))))
    (save-excursion (insert " ")))
  (when (and (company-manual-begin)
             (= company-candidates-length 1))
    (company-complete-common)))


;;;###autoload
(defun nasy/company-has-completion-p ()
  "Return non-nil if a completion candidate exists at point."
  (and (company-manual-begin)
       (= company-candidates-length 1)))


;;;###autoload
(defun nasy/company-toggle-auto-completion ()
  "Toggle as-you-type code completion."
  (interactive)
  (require 'company)
  (setq company-idle-delay (unless company-idle-delay 0.2))
  (message "Auto completion %s"
           (if company-idle-delay "enabled" "disabled")))


;;;###autoload
(defun nasy/company-complete ()
  "Bring up the completion popup. If only one result, complete it."
  (interactive)
  (require 'company)
  (when (ignore-errors
          (/= (point)
              (cdr (bounds-of-thing-at-point 'symbol))))
    (save-excursion (insert " ")))
  (when (and (company-manual-begin)
             (= company-candidates-length 1))
    (company-complete-common)))


;;;###autoload
(defun nasy/company-dabbrev ()
  "Invokes `company-dabbrev-code' in prog-mode buffers and `company-dabbrev'
    everywhere else."
  (interactive)
  (call-interactively
   (if (derived-mode-p 'prog-mode)
       #'company-dabbrev-code
     #'company-dabbrev)))


;;;###autoload
(defun nasy/company-whole-lines (command &optional arg &rest ignored)
  "`company-mode' completion backend that completes whole-lines, akin to vim's
    C-x C-l."
  (interactive (list 'interactive))
  (require 'company)
  (pcase command
    (`interactive (company-begin-backend 'nasy/company-whole-lines))
    (`prefix      (company-grab-line "^[\t\s]*\\(.+\\)" 1))
    (`candidates
     (all-completions
      arg
      (delete-dups
       (split-string
        (replace-regexp-in-string
         "^[\t\s]+" ""
         (concat (buffer-substring-no-properties (point-min) (line-beginning-position))
                 (buffer-substring-no-properties (line-end-position) (point-max))))
        "\\(\r\n\\|[\n\r]\\)" t))))))


;;;###autoload
(defun nasy/company-dict-or-keywords ()
  "`company-mode' completion combining `company-dict' and `company-keywords'."
  (interactive)
  (require 'company-dict)
  (require 'company-keywords)
  (let ((company-backends '((company-keywords company-dict))))
    (call-interactively #'company-complete)))


;;;###autoload
(defun nasy/company-dabbrev-code-previous ()
  "TODO"
  (interactive)
  (require 'company-dabbrev)
  (let ((company-selection-wrap-around t))
    (call-interactively #'nasy/company-dabbrev)
    (company-select-previous-or-abort)))
Configs
  • Company Mode
    (leaf company
      :hook prog-mode-hook
      :bind
      ("M-/"     . company-files)
      ("M-C-/"   . nasy/company-complete)
      ("C-<tab>" . nasy/company-complete)
      (:company-mode-map
       ("M-/" . nasy/company-complete))
      (:company-active-map
       ("M-/" . company-other-backend)
       ("C-n" . company-select-next)
       ("C-p" . company-select-previous))
      :custom ((company-tooltip-limit       . 10)
               (company-dabbrev-downcase    . nil)
               (company-dabbrev-ignore-case . t)
               (company-global-modes
                . '(not erc-mode message-mode help-mode gud-mode eshell-mode))
               `(company-frontends
                 . ,(if *c-box*
                        '(company-box-frontend)
                      '(company-pseudo-tooltip-frontend company-echo-metadata-frontend)))
               (company-dabbrev-other-buffers     . 'all)
               (company-tooltip-align-annotations . t)
               (company-minimum-prefix-length     . 2)
               (company-idle-delay                . .2)
               (company-tooltip-idle-delay        . .2)
               (company-require-match             . 'never))
      :config
      (add-hook 'after-change-major-mode-hook #'nasy/company-init-backends-h 'append)
      :defer-config
      (add-to-list 'completion-styles 'initials t)
      (setq company-backends '(company-capf))
      (defvar nasy/prev-whitespace-mode nil)
      (make-variable-buffer-local 'nasy/prev-whitespace-mode)
      (defvar nasy/show-trailing-whitespace nil)
      (make-variable-buffer-local 'nasy/show-trailing-whitespace)
      (defun pre-popup-draw ()
        "Turn off whitespace mode before showing company complete tooltip"
        (if whitespace-mode
            (progn
              (gsetq my-prev-whitespace-mode t)
              (whitespace-mode -1)))
        (gsetq nasy/show-trailing-whitespace show-trailing-whitespace)
        (gsetq show-trailing-whitespace nil))
      (defun post-popup-draw ()
        "Restore previous whitespace mode after showing company tooltip"
        (if nasy/prev-whitespace-mode
            (progn
              (whitespace-mode 1)
              (gsetq nasy/prev-whitespace-mode nil)))
        (gsetq show-trailing-whitespace nasy/show-trailing-whitespace))
      :advice
      (:before company-pseudo-tooltip-unhide pre-popup-draw)
      (:after  company-pseudo-tooltip-hide   post-popup-draw))
    
  • Company Prescient
    (leaf company-prescient
      :hook company-mode-hook)
    
  • Company Quickhelp
    (leaf company-quickhelp
      :when (not *c-box*)
      :bind
      (:company-active-map
       ("C-c h" . company-quickhelp-manual-begin))
      :hook company-mode-hook
      :custom
      (pos-tip-use-relative-coordinates . t))
    
  • Company Tabnine
    (leaf company-tabnine
      :custom
      `(company-tabnine-log-file-path
        . ,(concat company-tabnine-binaries-folder "/log")))
    
  • Company Flx
    (leaf company-flx
      :hook company-mode-hook)
    
  • Company Box
    (leaf company-box
      :when *c-box*
      :hook company-mode-hook
      :custom
      (company-box-show-single-candidate . t)
      (company-box-max-candidates        . 25)
      (company-box-icons-alist           . 'company-box-icons-all-the-icons)
      :config
      (gsetq
       company-box-icons-functions
       (cons #'nasy/company-box-icons--elisp-fn
             (delq 'company-box-icons--elisp
                   company-box-icons-functions)))
    
      (defun nasy/company-box-icons--elisp-fn (candidate)
        (when (derived-mode-p 'emacs-lisp-mode)
          (let ((sym (intern candidate)))
            (cond ((fboundp  sym) 'ElispFunction)
                  ((boundp   sym) 'ElispVariable)
                  ((featurep sym) 'ElispFeature)
                  ((facep    sym) 'ElispFace)))))
    
      (after-x 'all-the-icons
        (gsetq
         company-box-icons-all-the-icons
         (let ((all-the-icons-scale-factor 0.8))
           `((Unknown       . ,(all-the-icons-material "find_in_page"             :face 'all-the-icons-purple))
             (Text          . ,(all-the-icons-material "text_fields"              :face 'all-the-icons-green))
             (Method        . ,(all-the-icons-material "functions"                :face 'all-the-icons-yellow))
             (Function      . ,(all-the-icons-material "functions"                :face 'all-the-icons-yellow))
             (Constructor   . ,(all-the-icons-material "functions"                :face 'all-the-icons-yellow))
             (Field         . ,(all-the-icons-material "functions"                :face 'all-the-icons-yellow))
             (Variable      . ,(all-the-icons-material "adjust"                   :face 'all-the-icons-blue))
             (Class         . ,(all-the-icons-material "class"                    :face 'all-the-icons-cyan))
             (Interface     . ,(all-the-icons-material "settings_input_component" :face 'all-the-icons-cyan))
             (Module        . ,(all-the-icons-material "view_module"              :face 'all-the-icons-cyan))
             (Property      . ,(all-the-icons-material "settings"                 :face 'all-the-icons-lorange))
             (Unit          . ,(all-the-icons-material "straighten"               :face 'all-the-icons-red))
             (Value         . ,(all-the-icons-material "filter_1"                 :face 'all-the-icons-red))
             (Enum          . ,(all-the-icons-material "plus_one"                 :face 'all-the-icons-lorange))
             (Keyword       . ,(all-the-icons-material "filter_center_focus"      :face 'all-the-icons-lgreen))
             (Snippet       . ,(all-the-icons-material "short_text"               :face 'all-the-icons-lblue))
             (Color         . ,(all-the-icons-material "color_lens"               :face 'all-the-icons-green))
             (File          . ,(all-the-icons-material "insert_drive_file"        :face 'all-the-icons-green))
             (Reference     . ,(all-the-icons-material "collections_bookmark"     :face 'all-the-icons-silver))
             (Folder        . ,(all-the-icons-material "folder"                   :face 'all-the-icons-green))
             (EnumMember    . ,(all-the-icons-material "people"                   :face 'all-the-icons-lorange))
             (Constant      . ,(all-the-icons-material "pause_circle_filled"      :face 'all-the-icons-blue))
             (Struct        . ,(all-the-icons-material "streetview"               :face 'all-the-icons-blue))
             (Event         . ,(all-the-icons-material "event"                    :face 'all-the-icons-yellow))
             (Operator      . ,(all-the-icons-material "control_point"            :face 'all-the-icons-red))
             (TypeParameter . ,(all-the-icons-material "class"                    :face 'all-the-icons-red))
             (Template      . ,(all-the-icons-material "short_text"               :face 'all-the-icons-green))
             (ElispFunction . ,(all-the-icons-material "functions"                :face 'all-the-icons-red))
             (ElispVariable . ,(all-the-icons-material "check_circle"             :face 'all-the-icons-blue))
             (ElispFeature  . ,(all-the-icons-material "stars"                    :face 'all-the-icons-orange))
             (ElispFace     . ,(all-the-icons-material "format_paint"             :face 'all-the-icons-pink))))))
    
      (defun nasy/company-remove-scrollbar-a (orig-fn &rest args)
       "This disables the company-box scrollbar, because:
      https://github.com/sebastiencs/company-box/issues/44"
       (cl-letf (((symbol-function #'display-buffer-in-side-window)
                  (symbol-function #'ignore)))
         (apply orig-fn args)))
    
      :advice (:around
               company-box--update-scrollbar
               nasy/company-remove-scrollbar-a))
    
Emojify and all-the-icons
(leaf emojify
  :commands emojify-mode
  :when (version< emacs-version "27")
  :hook ((after-init-hook . global-emojify-mode))
  :custom (emojify-emoji-styles  . '(unicode github))
          (emojify-display-style . 'unicode))

(leaf all-the-icons
  :custom (inhibit-compacting-font-caches . t))
Fill Column
(leaf fill
  :doc "Filling text."
  :tag "emacs")
Unfill

Functions providing the inverse of Emacs' fill-paragraph and fill-region

https://github.com/purcell/unfill

(leaf unfill
  :doc "Functions providing the inverse of Emacs' fill-paragraph and fill-region"
  :url "https://github.com/purcell/unfill"
  :tag "convenience"
  :bind (("M-q" . unfill-toggle)))
Visual-fill-column

Emacs mode for wrapping visual-line-mode buffers at fill-column.

https://github.com/joostkremers/visual-fill-column

(leaf visual-fill-column
  :doc "Emacs mode for wrapping visual-line-mode buffers at fill-column."
  :url "https://github.com/joostkremers/visual-fill-column"
  :tag "convenience"
  :commands maybe-adjust-visual-fill-column
  :hook (visual-line-mode-hook
         (visual-fill-column-mode-hook . maybe-adjust-visual-fill-column))
  :config
  (defun maybe-adjust-visual-fill-column nil
    "Readjust visual fill column when the global font size is modified.\nThis 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))))
Find File in Project

Find file/directory and review Diff/Patch/Commit quickly everywhere.

https://github.com/technomancy/find-file-in-project

(leaf find-file-in-project
  :doc "Find file/directory and review Diff/Patch/Commit quickly everywhere."
  :url "https://github.com/technomancy/find-file-in-project"
  :tag "project" "convenience"
  :custom (ffip-use-rust-fd . t))
Flycheck
Autoloads
;;;###autoload
(defun save-buffer-maybe-show-errors ()
  "Save buffer and show errors if any."
  (interactive)
  (save-buffer)
  (when (not flycheck-current-errors)
    (flycheck-list-errors)))

;;;###autoload
(defun nasy/flycheck-inline-init ()
  "Flycheck-inline-mode init function"
  (gsetq flycheck-inline-display-function
         (lambda (msg pos)
           (let* ((ov (quick-peek-overlay-ensure-at pos))
                  (contents (quick-peek-overlay-contents ov)))
             (setf (quick-peek-overlay-contents ov)
                   (concat contents (when contents "\n") msg))
             (quick-peek-update ov)))
         flycheck-inline-clear-function #'quick-peek-hide))
configs

Flycheck

(leaf flycheck
  ;; :bind (("C-x C-s" . save-buffer-maybe-show-errors))
  :hook prog-mode-hook
  :custom
  (flycheck-display-errors-function
   . #'flycheck-display-error-messages-unless-error-list)
  (flycheck-check-syntax-automatically . '(save idle-change mode-enabled))
  (flycheck-display-errors-delay       . 0.25)
  :bind
  (:flycheck-error-list-mode-map
   ("C-n" . flycheck-error-list-next-error)
   ("C-p" . flycheck-error-list-previous-error)
   ("RET" . flycheck-error-list-goto-error)
   ([return]  . flycheck-error-list-goto-error))
  :config
  (defalias 'show-error-at-point-soon
    'flycheck-show-error-at-point)
  (add-to-list 'flycheck-emacs-lisp-checkdoc-variables 'sentence-end-double-space))

Flycheck checker for elisp package metadata.

https://github.com/purcell/flycheck-package

(leaf flycheck-package
  :doc "Flycheck checker for elisp package metadata."
  :url "https://github.com/purcell/flycheck-package"
  :tag "lisp"
  :after flycheck
  :config
  (flycheck-package-setup))

Flycheck inline

(leaf flycheck-inline
  :hook flycheck-mode-hook
  :mode-hook (nasy/flycheck-inline-init))
Grab Mac Link

Grab link from Mac Apps and insert it into Emacs.

https://github.com/xuchunyang/grab-mac-link.el

(leaf grab-mac-link
  :doc "Grab link from Mac Apps."
  :url "https://github.com/xuchunyang/grab-mac-link.el"
  :when *is-a-mac*)
Grep
(leaf grep
  :tag "builtin"
  :custom
  ((grep-highlight-matches grep-scroll-output) . t))
iBuffer
ibuffer

Ibuffer is an advanced replacement for BufferMenu, which lets you operate on buffers much in the same manner as Dired.

https://www.emacswiki.org/emacs/IbufferMode

(leaf ibuffer
  :doc "Ibuffer is an advanced replacement for BufferMenu, which lets you
operate on buffers much in the same manner as Dired."
  :url "https://www.emacswiki.org/emacs/IbufferMode"
  :tag "buffer" "convenience"
  :bind (("C-x C-b" . ibuffer))
  :hook ((ibuffer-mode-hook . ibuffer-switch-to-normal))
  :custom
  (ibuffer-saved-filter-groups
   . '(("Normal"
        ("Dired"      (mode . dired-mode))
        ("Emacs"     (or
                      (name . "^\\*dashboard\\*$")
                      (name . "^\\*scratch\\*$")
                      (name . "^\\*Messages\\*$")
                      (name . "^\\*Backtrace\\*$")))
        ("Term"       (mode . vterm-mode))
        ("Text"      (or
                      (mode . org-mode)
                      (mode . markdown)
                      (mode . rst-mode)
                      (mode . text-mode)))
        ("TeX"        (mode . tex-mode))
        ("Languages" (or
                      (mode . emacs-lisp-mode)
                      (mode . haskell-mode)
                      (mode . javascript-mode)
                      (mode . lisp-mode)
                      (mode . python-mode)
                      (mode . ruby-mode)
                      (mode . rust-mode)
                      (mode . html-mode)
                      (mode . css-mode)
                      (mode . prog-mode)))
        ("GNUs"      (or
                      (mode . message-mode)
                      (mode . bbdb-mode)
                      (mode . mail-mode)
                      (mode . gnus-group-mode)
                      (mode . gnus-summary-mode)
                      (mode . gnus-article-mode)
                      (name . "^\\.bbdb$")
                      (name . "^\\.newsrc-dribble")))
        ("Magit"      (name . "^magit"))
        ("Help"      (or
                      (name . "^\\*Help\\*$")
                      (name . "^\\*Apropos\\*$")
                      (name . "^\\*info\\*$")
                      (name . "^\\*helpful")))
        ("Custom"    (or
                      (mode . custom-mode)
                      (name . "^\\*Customize")))
        ("Helm"       (mode . helm-major-mode)))))
  (ibuffer-show-empty-filter-groups . nil)
  (ibuffer-default-sorting-mode     . 'filename/process)
  :defer-config
  (define-ibuffer-column size-h
    (:name "Size" :inline t)
    (file-size-human-readable (buffer-size)))

  (gsetq 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)))
  (defun ibuffer-switch-to-normal ()
    "ibuffer swith to normal filter groups."
    (ibuffer-switch-to-saved-filter-groups "Normal")))
ibuffer vc

Let Emacs' ibuffer-mode group files by git project etc., and show file state

https://github.com/purcell/ibuffer-vc

(leaf ibuffer-vc
  :doc "Let Emacs' ibuffer-mode group files by git project etc., and show file state"
  :url "https://github.com/purcell/ibuffer-vc"
  :tag "convenience")
all-the-icons-ibuffer

Display icons for all buffers in ibuffer.

https://github.com/seagle0128/all-the-icons-ibuffer

(leaf all-the-icons-ibuffer
  :doc "Display icons for all buffers in ibuffer."
  :url "https://github.com/seagle0128/all-the-icons-ibuffer"
  :tag "convenience" "icons" "ibuffer"
  :hook after-init-hook)
imenu list

Emacs plugin to show the current buffer's imenu entries in a seperate buffer.

https://github.com/bmag/imenu-list

(leaf imenu-list
  :doc "Emacs plugin to show the current buffer's imenu entries in a seperate buffer"
  :url "https://github.com/bmag/imenu-list"
  :tag "tools" "convenience"
  :bind (("C-." . imenu-list-smart-toggle))
  :custom (imenu-list-auto-resize . t))
isearch

Isearch, that is, incremental search, is the standard way to search in vanilla Emacs.

https://www.emacswiki.org/emacs/IncrementalSearch

(leaf isearch
  :doc "Isearch, that is, incremental search, is the standard way to search in
vanilla Emacs."
  :url "https://www.emacswiki.org/emacs/IncrementalSearch"
  :tag "matching"
  :bind (:isearch-mode-map
         ([remap isearch-delete-char]
          . isearch-del-char)
         ("C-w"
          . isearch-yank-symbol)
         ([(control return)]
          . isearch-exit-other-end)
         ("C-o"
          . isearch-occur))

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

Languages

(nasy/local-repo langs)
(require 'nasy-langs)

Packages

(setq parinfer-rust-auto-download t
      parinfer-rust-library
      (no-littering-expand-var-file-name "parinfer-rust/parinfer-rust-darwin.so"))

(straight-register-package
 '(parinfer-rust-mode :type git
                      :host github
                      :repo "justinbarclay/parinfer-rust-mode"))

(nasy/s-u-p
  ;; lisps
  cl-lib-highlight
  elisp-def
  highlight-quoted
  ipretty
  macrostep
  parinfer-rust-mode

  ;; lsp-mode
  dap-mode
  lsp-mode
  lsp-treemacs
  lsp-ui

  company-restclient
  elvish-mode
  fish-completion
  fish-mode
  markdown-mode
  ob-elvish
  ob-restclient
  pandoc-mode
  restclient
  toml-mode
  yaml-mode
  (:when *rust* cargo rust-mode))

Configs

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

Clangd or ccls.

Packages
(nasy/s-u-p macrostep)
(when *ccls*
    (nasy/s-u-p ccls))
Configs
  • macrostep
    (use-package macrostep
      :defer t
      :general
      (:keymaps 'c-mode-map
                "C-c e" #'macrostep-expand)
      (:keymaps 'c++-mode-map
                "C-c e" #'macrostep-expand)
      (:keymaps 'objc-mode-map
                "C-c e" #'macrostep-expand))
    
  • clangd
    (use-package lsp-mode
      :if *clangd*
      :hook (((c-mode c++-mode objc-mode) . lsp-deferred))
      :init (setq-default lsp-clients-clangd-executable *clangd*))
    
  • ccls
    (when *ccls*
      (use-package ccls
        :preface
        (defun ccls/load ()
          (require 'ccls)
          (lsp-deferred))
        :hook (((c-mode c++-mode objc-mode) . ccls/load))
        :init
        (gsetq ccls-executable *ccls*
               ccls-initialization-options
               '(:clang (:extraArgs
                         ["-isysroot"
                          "/Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX.sdk"])
                 :index (:comments 2)
                 :completion (:detailedLabel t)
                 ccls-sem-highlight-method 'font-lock))
        (gsetq ccls-sem-function-colors
               '("#e5b124" "#927754" "#eb992c" "#e2bf8f" "#d67c17"
                 "#88651e" "#e4b953" "#a36526" "#b28927" "#d69855")
               ccls-sem-macro-colors
               '("#e79528" "#c5373d" "#e8a272" "#d84f2b" "#a67245"
                 "#e27a33" "#9b4a31" "#b66a1e" "#e27a71" "#cf6d49")
               ccls-sem-namespace-colors
               '("#aa96da" "#fcbad3" "#ffffd2" "#a8d8ea" "#ffcfdf"
                 "#fefdca" "#e0f9b5" "#a5dee5" "#eef9bf" "#a7e9af")
               ccls-sem-parameter-colors
               '("#aa96da" "#fcbad3" "#ffffd2" "#a8d8ea" "#ffcfdf"
                 "#fefdca" "#e0f9b5" "#a5dee5" "#eef9bf" "#a7e9af")
               ccls-sem-type-colors
               '("#e1afc3" "#d533bb" "#9b677f" "#e350b6" "#a04360"
                 "#dd82bc" "#de3864" "#ad3f87" "#dd7a90" "#e0438a"))
        :config
        (ccls-use-default-rainbow-sem-highlight)
        (defun ccls/callee ()
          (interactive)
          (lsp-ui-peek-find-custom "$ccls/call" '(:callee t)))
        (defun ccls/caller ()
          (interactive)
          (lsp-ui-peek-find-custom "$ccls/call"))
        (defun ccls/vars (kind)
          (lsp-ui-peek-find-custom "$ccls/vars" `(:kind ,kind)))
        (defun ccls/base (levels)
          (lsp-ui-peek-find-custom "$ccls/inheritance" `(:levels ,levels)))
        (defun ccls/derived (levels)
          (lsp-ui-peek-find-custom "$ccls/inheritance" `(:levels ,levels :derived t)))
        (defun ccls/member (kind)
          (lsp-ui-peek-find-custom "$ccls/member" `(:kind ,kind)))
    
        ;; The meaning of :role corresponds to https://github.com/maskray/ccls/blob/master/src/symbol.h
    
        ;; References w/ Role::Address bit (e.g. variables explicitly being taken addresses)
        (defun ccls/references-address ()
          (interactive)
          (lsp-ui-peek-find-custom "textDocument/references"
           (plist-put (lsp--text-document-position-params) :role 128)))
    
        ;; References w/ Role::Dynamic bit (macro expansions)
        (defun ccls/references-macro ()
          (interactive)
          (lsp-ui-peek-find-custom "textDocument/references"
           (plist-put (lsp--text-document-position-params) :role 64)))
    
        ;; References w/o Role::Call bit (e.g. where functions are taken addresses)
        (defun ccls/references-not-call ()
          (interactive)
          (lsp-ui-peek-find-custom "textDocument/references"
           (plist-put (lsp--text-document-position-params) :excludeRole 32)))
    
        ;; References w/ Role::Read
        (defun ccls/references-read ()
          (interactive)
          (lsp-ui-peek-find-custom "textDocument/references"
           (plist-put (lsp--text-document-position-params) :role 8)))
    
        ;; References w/ Role::Write
        (defun ccls/references-write ()
          (interactive)
          (lsp-ui-peek-find-custom "textDocument/references"
           (plist-put (lsp--text-document-position-params) :role 16)))
    
        ;; xref-find-apropos (workspace/symbol)
    
        (defun my/highlight-pattern-in-text (pattern line)
          (when (> (length pattern) 0)
            (let ((i 0))
             (while (string-match pattern line i)
               (setq i (match-end 0))
               (add-face-text-property (match-beginning 0) (match-end 0) 'isearch t line))
             line)))
    
        (after! lsp-methods
          ;;; Override
          ;; This deviated from the original in that it highlights pattern appeared in symbol
          (defun lsp--symbol-information-to-xref (pattern symbol)
           "Return a `xref-item' from SYMBOL information."
           (let* ((location (gethash "location" symbol))
                  (uri (gethash "uri" location))
                  (range (gethash "range" location))
                  (start (gethash "start" range))
                  (name (gethash "name" symbol)))
             (xref-make (format "[%s] %s"
                                (alist-get (gethash "kind" symbol) lsp--symbol-kind)
                                (my/highlight-pattern-in-text (regexp-quote pattern) name))
                        (xref-make-file-location (string-remove-prefix "file://" uri)
                                                 (1+ (gethash "line" start))
                                                 (gethash "character" start)))))
    
          (cl-defmethod xref-backend-apropos ((_backend (eql xref-lsp)) pattern)
            (let ((symbols (lsp--send-request (lsp--make-request
                                               "workspace/symbol"
                                               `(:query ,pattern)))))
              (mapcar (lambda (x) (lsp--symbol-information-to-xref pattern x)) symbols))))))
    
English
Dict
(straight-use-package 'bing-dict)
(use-package bing-dict
  :bind (("C-c d" . bing-dict-brief))
  :init (gsetq bing-dict-show-thesaurus  'both
               bing-dict-vocabulary-save t
               bing-dict-cache-auto-save t
               bing-dict-vocabulary-file
               (no-littering-expand-var-file-name "bing-dict/vocabulary.org")
               bing-dict-cache-file
               (no-littering-expand-var-file-name "bing-dict/bing-dict-save.el")))
Spell
(use-package ispell
  :if *ispell*
  :init
  (gsetq-default ispell-program-name   *ispell*
                 ispell-silently-savep t
                 ispell-dictionary     "english"
                 ispell-personal-dictionary
                 (no-littering-expand-var-file-name "ispell/dictionary"))
  (when (string-suffix-p "aspell" *ispell*)
    (gsetq-default ispell-extra-args '("--reverse"))))

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

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

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

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

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

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

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

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

  If optional AND-THEN-FIND-THIS-TAG argument is present it is used
  with function `xref-find-definitions' after new table was
  generated."
    (interactive)
    (let* ((dir (haskell-cabal--find-tags-dir))
           (command (haskell-cabal--compose-hasktags-command dir)))
      (if (not command)
          (error "Unable to compose hasktags command")
        ;; I disabled the noisy shell command output.
        ;; The original is (shell-command command)
        (call-process-shell-command command nil "*Shell Command Output*" t)
        (haskell-mode-message-line "Tags generated.")
        (when and-then-find-this-tag
          (let ((tags-file-name dir))
            (xref-find-definitions and-then-find-this-tag)))))))
LSP Haskell
(straight-use-package 'lsp-haskell)
(use-package lsp-haskell
  :preface
  (defun start-lsp-haskell ()
    (require 'lsp)
    (require 'lsp-haskell)
    (lsp-deferred))
  :defer t
  :hook ((haskell-mode . start-lsp-haskell))
  :init
  (nasy/add-company-backend 'haskell-mode '(company-capf
                                            company-lsp
                                            company-files
                                            :with company-tabnine company-yasnippet))
  ;; (gsetq lsp-haskell-process-path-hie "hie-8.6.5")
  ;; 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
  ;; (gsetq lsp-haskell-process-path-hie "ghcide")
  ;; (gsetq lsp-haskell-process-args-hie '())
  )
intero
(when *intero*
  (straight-use-package 'intero)
  (use-package intero
    :hook ((haskell-mode . intero-mode))
    :config
    (define-key intero-mode-map (kbd "M-?") nil)
    (define-key intero-mode-map (kbd "C-c C-r") nil)))
Structured Haskell Mode
(if *struct-hs*
    (progn
      (add-to-list 'load-path *struct-hs-path*)
      (require 'shm)
      (setq shm-program-name *struct-hs*)
      (add-hook #'haskell-mode-hook #'structured-haskell-mode))
  (progn
    (when *struct-hs*
      (message (concat "*NOTE* about structured-haskell-mode:\n"
                       "https://github.com/projectional-haskell/structured-haskell-mode\n"
                       "No structured-haskell-mode elisp find.\n"
                       "If you want to use it, \n"
                       "please install it and config its variables *struct-hs-path* in user-config.el\n")))))
haskell snippets
(straight-use-package 'haskell-snippets)
HTML
(leaf lsp-html
  :hook ((html-mode-hook . lsp-deferred)))
JavaScript & TypeScript
(leaf lsp-mode
  :hook ((javascript-mode-hook . lsp-deferred)))
Language Server Protocol & Debug Adapter Protocol   languages

Emacs client/library for the Language Server Protocol

lsp-mode   languages
(leaf lsp-mode
  :doc "Language Server Protocol Support for Emacs."
  :url "https://github.com/emacs-lsp/lsp-mode"
  :tag "languages"
  :hook
  (kill-emacs-hook . (lambda () (setq lsp-restart 'ignore)))
  :mode-hook
  (nasy/lsp-init)
  (lsp-diagnostics-mode 1)
  :init
  (defun nasy/lsp-init ()
    "Nasy lsp mode init."
    (flycheck-inline-mode -1)
    (when lsp-enable-symbol-highlighting
      (add-hook #'lsp-on-idle-hook #'lsp--document-highlight nil t)
      (lsp--info "Symbol highlighting enabled in current buffer.")))
  :custom
  ((lsp-log-io
    lsp-print-performance
    lsp-report-if-no-buffer) . *debug*)
  ((lsp-log-max
    lsp-inhibit-message
    lsp-enable-snippet
    lsp-eldoc-enable-hover
    lsp-eldoc-render-all
    lsp-enable-imenu
    lsp-enable-xref
    lsp-enable-links
    lsp-enable-indentation
    lsp-enable-on-type-formatting
    lsp-enable-semantic-highlighting
    lsp-enable-symbol-highlighting
    lsp-signature-auto-activate
    lsp-enable-text-document-color
    lsp-enable-folding
    lsp-prefer-capf) . t)
  ((lsp-keep-workspace-alive
    lsp-auto-guess-root
    lsp-auto-configure
    lsp-enable-completion-at-point
    lsp-enable-file-watchers))
  (lsp-restart . 'interactive)
  (lsp-diagnostics-package . :auto))
lsp-ui   languages tools
(leaf lsp-ui
  :doc "UI integrations for lsp-mode."
  :url "https://github.com/emacs-lsp/lsp-ui"
  :tag "languages" "tools"
  :hook lsp-mode-hook
  :mode-hook (lsp-ui-sideline-mode 1)
  :custom
  (lsp-ui-doc-enable . t)
  ((lsp-ui-doc-include-signature
    lsp-ui-sideline-show-hover
    lsp-ui-sideline-ignore-duplicate) . t)
  :defer-config
  (require 'lsp-ui-peek))
lsp-treemacs   languages
(leaf lsp-treemacs
  :doc "lsp-mode ❤ treemacs."
  :url "https://github.com/emacs-lsp/lsp-treemacs"
  :tag "languages"
  :custom
  (lsp-metals-treeview-show-when-views-received . t)
  :defer-config
  (lsp-treemacs-sync-mode t))
Lisp
cl-lib-highlight
(leaf cl-lib-highlight
  :after lisp-mode
  :config
  (cl-lib-highlight-initialize))
elisp-def
(leaf elisp-def
  :hook (((emacs-lisp-mode-hook ielm-mode-hook) . elisp-def-mode)))
Highlight-quoted
(leaf highlight-quoted
  :hook ((emacs-lisp-mode-hook . highlight-quoted-mode)))
ipretty   buffer emacslisp pprint

Interactive Emacs Lisp pretty-printing.

ipretty.el provides interactive functions to pretty-print the result of an expression and a global mode ipretty-mode that advices eval-print-last-sexp to pretty print.

https://framagit.org/steckerhalter/ipretty

(leaf ipretty
  :doc "Interactive Emacs Lisp pretty-printing"
  :url "https://framagit.org/steckerhalter/ipretty"
  :tag "buffer" "emacslisp" "pprint"
  :bind (("C-h C-j" . ipretty-last-sexp)
         ("C-h C-k" . ipretty-last-sexp-other-buffer)))
  :hook after-init-hook
lisp-mode
(leaf 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
  (:emacs-lisp-mode-map
   ([remap eval-expression] . pp-eval-expression)
   ("C-x C-e"               . eval-last-sexp-or-region)))
macrostep
(leaf macrostep
  :bind
  (:emacs-lisp-mode-map
   ("C-c e" . macrostep-expand)))
parinfer-rust-mode
(leaf parinfer-rust-mode
  :custom
  `(parinfer-rust-library
    . ,(no-littering-expand-var-file-name "parinfer-rust/parinfer-rust-darwin.so"))
  (parinfer-rust-auto-download . t)
  :hook `(,lisp-modes-hooks))
Markdown
(leaf markdown-mode
  :mode ("INSTALL\\'"
         "CONTRIBUTORS\\'"
         "LICENSE\\'"
         "README\\'"
         "\\.markdown\\'"
         "\\.md\\'"))
Python
Autoloads
;;;###autoload
(defcustom nasy*python-buffer "vterm"
  "Nasy Python Buffer"
  :group 'python-mode
  :type 'string)

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

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

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

;;;###autoload
(defun nasy/python-switch-to-shell ()
  "Switch to inferior Python process buffer."
  (interactive "p")
  (let ((proc (get-buffer-process nasy:python-buffer)))
    (unless proc
      (error "No process found"))
    (pop-to-buffer nasy*python-buffer)))
config
(general-define-key
 :prefix "C-c"
 :keymaps 'python-mode-map
 "C-b" 'nasy/python-send-buffer
 "C-r" 'nasy/python-send-region
 "C-c" 'nasy/python-send-defun
 "C-z" 'nasy/python-switch-to-shell)
(general-define-key
 :keymaps 'python-mode-map
 "<S-return>" 'nasy/python-send-region)


(defun python-flycheck-setup ()
  "Add python checker for lsp-ui."
  (after-x 'lsp-ui
    (flycheck-add-next-checker 'lsp              'python-flake8))
    ;; flake8 already have python-mypy and python-pylint as the next checker
    ;; (flycheck-add-next-checker 'python-flake8    'python-mypy)))
  (flycheck-disable-checker 'python-pylint)
  (flycheck-remove-next-checker 'python-flake8 'python-pylint))
pylance
(leaf nasy-langs-pylance
  :preface
  (defun start-lsp-pylance ()
    "Start lsp-pylance."
    (require 'nasy-langs-pylance)
    (python-flycheck-setup)
    ;; (gsetq elpy-modules (remove 'elpy-module-autodoc elpy-modules))
    ;; (gsetq elpy-modules (remove 'elpy-module-eldoc   elpy-modules))
    (lsp-deferred))
  :hook
  (python-mode-hook . start-lsp-pylance))
restclient.el

HTTP REST client tool for emacs

https://github.com/pashky/restclient.el

(leaf restclient
  :init
  (nasy/add-company-backend
    'restclient-mode
    '(company-restclient company-files)))
Rust

Include rust-mode, rls and Cargo.

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

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

Yaml
(leaf lsp-yaml
  :hook ((yaml-mode-hook . lsp-deferred)))

Org Mode

(nasy/local-repo org)
(require 'nasy-org)

Packages

I use org with org-plus-contrib

(nasy/s-u-p
  org-plus-contrib

  org-cliplink
  org-pdfview
  org-superstar
  org-wc
  toc-org)

Autoloads

;; Exclude DONE state tasks from refile targets
;;;###autoload
(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)

;;;###autoload
(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)))

;;;###autoload
(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)))

;;;###autoload
(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)))

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

;;;###autoload
(defun org-agenda-log-mode-colorize-block ()
  "Set different line spacing based on clock time duration."
  (save-excursion
    (let* ((colors (cl-case (alist-get 'background-mode (frame-parameters))
                     ('light
                      (list "#a7e9af" "#75b79e" "#6a8caf" "#eef9bf"))
                     ('dark
                      (list "#a7e9af" "#75b79e" "#6a8caf" "#eef9bf"))))
           pos
           duration)
      (nconc colors colors)
      (goto-char (point-min))
      (while (setq pos (next-single-property-change (point) 'duration))
        (goto-char pos)
        (when (and (not (equal pos (point-at-eol)))
                  (setq duration (org-get-at-bol 'duration)))
          ;; larger duration bar height
          (let ((line-height (if (< duration 15) 1.0 (+ 0.5 (/ duration 30))))
                (ov (make-overlay (point-at-bol) (1+ (point-at-eol)))))
            (overlay-put ov 'face `(:background ,(car colors) :foreground "black"))
            (setq colors (cdr colors))
            (overlay-put ov 'line-height line-height)
            (overlay-put ov 'line-spacing (1- line-height))))))))

;;;###autoload
(defun show-org-clock-in-header-line ()
  "Show the clocked-in task in header line"
  (setq-default header-line-format '((" " org-mode-line-string ""))))

;;;###autoload
(defun hide-org-clock-from-header-line ()
  "Hide the clocked-in task from header line"
  (setq-default header-line-format nil))

Configs

Basic Configs
(leaf org
  :bind (:org-src-mode-map
         ("C-c _" . org-edit-src-exit))
  :hook ((org-mode-hook . auto-fill-mode)
         (org-mode-hook . nasy/org-fix-saveplace)
         (org-mode-hook . org-prettify-source-block-mode))
  :advice
  (:after
   org-refile
   (lambda (&rest _) (org-save-all-org-buffers)))
  (:around
   org-html-paragraph
   nasy/org-html-paragraph-advice))
(leaf org
  :custom
  ((org-archive-location  . "%s_archive::* Archive")
   (org-archive-mark-done . nil)

   (org-catch-invisible-edits . 'smart)

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

   (org-edit-timestamp-down-means-later . t)

   (org-ellipsis . " ﹅")

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

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

   (org-fast-tag-selection-single-key . 'expert)

   ;; org appearance
   ((org-allow-promoting-top-level-subtree
     org-cycle-level-faces
     org-fontify-done-headline
     org-fontify-emphasized-text
     org-fontify-todo-headline
     org-fontify-whole-block-delimiter-line
     org-fontify-whole-heading-line
     org-hide-emphasis-markers)
    . t)
   (org-hide-leading-stars . nil)

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

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

   (org-indent-mode-turns-on-hiding-stars . nil)

   (org-pretty-entities . t)

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

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

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

   (org-outline-path-complete-in-steps . nil)

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

   (org-startup-indented  . t)
   (org-startup-folded    . 'content)
   (org-startup-truncated . nil)

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

   (org-support-shift-select . t)

   (org-tags-column . -67)

   ;; to-do settings
   (org-todo-keywords . '((sequence
                           "TODO(t)"
                           "WIP(w/!)"
                           "WAIT([email protected]/!)"
                           "HOLD(h)"
                           "|"
                           "CANCELLED([email protected]/!)"
                           "DONE(d!/!)")))
   (org-todo-repeat-to-state . "NEXT")
   (org-todo-keyword-faces   . '(("NEXT" :inherit warning)
                                 ("WAIT" :inherit font-lock-string-face)))

   (org-babel-python-command . "python"))
  :defer-config
  (nasy/add-company-backend 'org-mode 'company-tabnine)
  ;; --------
  (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)
     (restclient . t)
     (ruby       . t)
     (screen     . nil)
     (,(if (locate-library "ob-sh") 'sh 'shell) . t)
     (sql        . nil)
     (sqlite     . t)))
  ;; --------
  (gsetq luamagick
         '(luamagick
           :programs ("lualatex" "convert")
           :description "pdf > png"
           :message "you need to install lualatex and imagemagick."
           :use-xcolor t
           :image-input-type "pdf"
           :image-output-type "png"
           :image-size-adjust (1.0 . 1.0)
           :latex-compiler ("lualatex -interaction nonstopmode -output-directory %o %f")
           :image-converter ("convert -density %D -trim -antialias %f -quality 100 %O")))
  (add-to-list 'org-preview-latex-process-alist luamagick)

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

  (require 'org-tempo nil t)
  (after-x 'ox
    (let ((oxs '(ox-rst
                 ox-pandoc)))
      (dolist (language oxs)
        (straight-use-package language)
        (require language nil t)))))
Org Agenda
(leaf org-agenda
  :hook ((org-agenda-finalize-hook . org-agenda-log-mode-colorize-block))
  :after org
  :custom
  (org-agenda-clockreport-parameter-plist . '(:link t :maxlevel 3))
  (org-agenda-compact-blocks   . t)
  (org-agenda-include-diary    . nil)
  (org-agenda-span             . 'week)
  (org-agenda-start-on-weekday . nil)
  (org-agenda-start-day        . "-1d")
  (org-agenda-sticky           . nil)
  (org-agenda-window-setup     . 'current-window)

  (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-time-grid
   . '((daily today weekly require-timed remove-match)
       (0 600 900 1200 1300 1600 1800 2000 2200 2400 2600)
       "......"
       "-----------------------------------------------------"))
  (org-agenda-prefix-format
   . '((agenda . " %i %+15c\t%?-15t% s")
       (todo   . " %i %+15c\t")
       (tags   . " %i %+15c\t")
       (search . " %i %+15c\t")))
  :init
  (after-x 'all-the-icons
    (gsetq
     org-agenda-category-icon-alist
     `(("Tasks"        ,(list (all-the-icons-faicon  "tasks"            :height 0.8 :v-adjust 0)) nil nil :ascent center)
       ("Calendar"     ,(list (all-the-icons-octicon "calendar"         :height 0.8 :v-adjust 0)) nil nil :ascent center)
       ("Appointments" ,(list (all-the-icons-faicon  "calendar-check-o" :height 0.8 :v-adjust 0)) nil nil :ascent center)))))
Org Capture
(leaf org-capture
  :defvar org-capture-templates
  :defer-config
  (add-to-list 'org-capture-templates '("t" "Tasks"))

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

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

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

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

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

  (add-to-list 'org-capture-templates
               '("n" "Notes" entry
                 (file "~/notes/notes.org")
                 "* %^{heading} %t %^g\n  %?\n")))
Org clock
(leaf org-clock
  :custom
  ((org-clock-persist
    org-clock-in-resume
    ;; Save clock data and notes in the LOGBOOK drawer
    org-clock-into-drawer
    ;; Save state changes in the LOGBOOK drawer
    org-log-into-drawer
    ;; Removes clocked tasks with 0:00 duration
    org-clock-out-remove-zero-time-clocks) . t)
  ;; Show clock sums as hours and minutes, not "n days" etc.
  (org-time-clocksum-format
   . '(:hours "%d" :require-hours t :minutes ":%02d" :require-minutes t))
  :hook ((org-clock-in-hook . show-org-clock-in-header-line)
         ((org-clock-out-hook . org-clock-cancel) . hide-org-clock-from-header))
  :bind (: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 Pomodoro
(leaf org-pomodoro
  :custom (org-pomodoro-keep-killed-pomodoro-time . t)
  :bind (:org-agenda-mode-map
         ("P" . org-pomodoro)))
Org Prettify Source Block
(defgroup org-prettify-source-block nil
  "Prettify org-mode source block markers."
  :group 'org-mode
  :prefix "org-prettify-source-block"
  :version "0.1")

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

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

(defvar opsb-block-alist `(("#+begin_src" . ?λ) ;; ╦ ➤ 🖝 ➟ ➤ ✎ ✎
                           ("#+end_src"   . ?⌞) ;; ╩ □
                           ("#+header:" . ,opsb-ob-header-symbol)
                           ("#+begin_comment" . ?✎)
                           ("#+end_comment" . ?⌞)
                           ("#+begin_notes" . ?➤)
                           ("#+end_notes" . ?⌞)
                           ("#+begin_quote" . ?»)
                           ("#+end_quote" . ?⌞)))

(defun opsb-org-prettify-src--update ()
  (let ((case-fold-search t)
        (re "^[ \t]*#\\+begin_src[ \t]+[^ \f\t\n\r\v]+[ \t]*")
        found)
    (save-excursion
      (goto-char (point-min))
      (while (re-search-forward re nil t)
        (goto-char (match-end 0))
        (let ((args (org-trim
                     (buffer-substring-no-properties (point)
                                                     (line-end-position)))))
          (when (org-string-nw-p args)
            (let ((new-cell (cons args opsb-ob-header-symbol)))
              (cl-pushnew new-cell prettify-symbols-alist :test #'equal)
              (cl-pushnew new-cell found :test #'equal)))))

      (setq prettify-symbols-alist
            (cl-set-difference prettify-symbols-alist
                               (cl-set-difference
                                (cl-remove-if-not
                                 (lambda (elm)
                                   (eq (cdr elm) opsb-ob-header-symbol))
                                 prettify-symbols-alist)
                                found :test #'equal)))

      ;; Clean up old font-lock-keywords.
      (font-lock-remove-keywords nil prettify-symbols--keywords)
      (setq prettify-symbols--keywords (prettify-symbols--make-keywords))
      (font-lock-add-keywords nil prettify-symbols--keywords)
      (while (re-search-forward re nil t)
        (font-lock-flush (line-beginning-position) (line-end-position))))))

(defun opsb-org-prettify-src ()
  "Hide src options via `prettify-symbols-mode'.
    `prettify-symbols-mode' is used because it has
    uncollapsing. It may not be efficient."
  (let* ((case-fold-search t)
         (at-src-block
          (save-excursion
            (beginning-of-line)
            (looking-at "^[ \t]*#\\+begin_src[ \t]+[^ \f\t\n\r\v]+[ \t]*"))))
    ;; Test if we moved out of a block.