8000 GitHub - MatthewZMD/.emacs.d at 2.10.0
[go: up one dir, main page]
More Web Proxy on the site http://driver.im/
Skip to content

MatthewZMD/.emacs.d

Repository files navigation

M-EMACS

About

M-EMACS is a custom GNU Emacs setup and configurations that aims not only to enhance the default Emacs experience, and hopefully be a sample that everyone can easily navigate and reference through a highly detailed README that contains 99% of the entire configuration code.

As a young EMACSer, I have experienced the struggle to find a detailed configuration that is loosely coupled and highly readable. This mostly due to the nature of source codes, sometimes comments are harder to notice or simply not enough. Therefore I decided to construct this README and present any human-readable explanation in a much more human-friendly way. Anyone, particularly Emacs beginners who have no idea where to start with their personal config, is more than welcome to read through this document and copy/paste any part to use it on their own.

This configuration is designed and tested for GNU Emacs 26.1 and above only. However, it is suggested to use emacs27, the latest version currently available.

(when (version< emacs-version "26.1")
  (error "M-EMACS requires Emacs 26.1 and above!"))

About README

This README is originated from init.org that is generated using M-x org-gfm-export-to-markdown. Every block of code is generated through this function - it exports the section of code from the elisp/ directory. You will not see their presence in init.org.

Installation

  1. Install GNU Emacs. If you are using Ubuntu, emacs-snapshot is a great way to get latest version of Emacs.

    sudo add-apt-repository -y ppa:ubuntu-elisp
    sudo apt-get update
    sudo apt-get install emacs-snapshot
    
  2. Clone this repo to HOME or ~/ path using git and update all the submodules.

    git clone --recurse-submodules -j8 https://github.com/MatthewZMD/.emacs.d.git
    cd .emacs.d
    
  3. Ensure a stable connection to Melpa Packages, then open Emacs.

  4. Enter y when prompted with Auto-update packages now?, wait for all packages to install.

  5. In your favorite browser, Ctrl-F Prerequisite through this webpage and follow the Prerequisite instructions.

  6. Restart Emacs.

Further Updates

I will be updating M-EMACS from time to time, it is best to git pull once a while to stay up to date.

Please also execute git submodule update --recursive --remote to sync with all the submodules.

Modification

You have the permission to use, modify, distribute in any way you want. However, what is free stays free. After all, this is GPL.

Remember you must manually sync this README with all the new changes you made by:

  1. Please do NOT edit README.md file, edit init.org instead!
  2. If you add a new mode, create a new <file-name>.el file in elisp/ directory.
  3. Put (require '<file-name>) in init.el accordingly.
  4. Add #+INCLUDE: "~/.emacs.d/elisp/<place-holder>.el" src emacs-lisp :range-begin "<start-line-wrapper-exclusive>" :range-end "<end-line-wrapper-exclusive>" in the appropriate section in init.org.
  5. Enter C-x C-s to save and update :lines. (if you don't see the updated effect, run M-x update-includes manually)
  6. Call M-x org-gfm-export-to-markdown to update this README.

Contribution

If you spotted a bug or you have any suggestions, please fill in an issue. If you have something to fix, feel free to create a pull request.

Special Thanks

Everyone starts somewhere, and I started here.

Table of Contents :TOC_2_ORG:

Startup

Lexical Binding

Use lexical-binding. Why?

Until Emacs 24.1 (June 2012), Elisp only had dynamically scoped variables, a feature, mostly by accident, common to old lisp dialects. While dynamic scope has some selective uses, it’s widely regarded as a mistake for local variables, and virtually no other languages have adopted it.

;;; init.el --- -*- lexical-binding: t -*-

Early Init

Emacs27 introduces early-init.el, which is run before init.el, before package and UI initialization happens.

Defer Garbage Collection

Defer garbage collection further back in the startup process, according to hlissner.

The GC eats up quite a bit of time, easily doubling startup time. The trick is to turn up the memory threshold as early as possible.

(setq gc-cons-threshold 80000000
      gc-cons-percentage 0.6)

Disable package-enable-at-startup

Package initialize occurs automatically, before user-init-file is loaded, but after early-init-file. We handle package initialization, so we must prevent Emacs from doing it early!

(setq package-enable-at-startup nil)

Unset file-name-handler-alist

Every file opened and loaded by Emacs will run through this list to check for a proper handler for the file, but during startup, it won’t need any of them.

(setq file-name-handler-alist-original file-name-handler-alist)
(setq file-name-handler-alist nil)

Disable site-run-file

(setq site-run-file nil)

Disable Unnecessary Interface

It will be faster to disable them here before they've been initialized.

(unless (and (display-graphic-p) (eq system-type 'darwin))
  (push '(menu-bar-lines . 0) default-frame-alist))
(push '(tool-bar-lines . 0) default-frame-alist)
(push '(vertical-scroll-bars) default-frame-alist)

Restore Default After Startup

A large gc-cons-threshold will cause freezing and stuttering during long-term interactive use.

(add-hook 'emacs-startup-hook
          (lambda ()
            (setq-default gc-cons-threshold better-gc-cons-threshold ;; 16mb
                          gc-cons-percentage 0.1)
            (setq file-name-handler-alist file-name-handler-alist-original)
            (makunbound 'file-name-handler-alist-original)))

Garbage Collection

Garbage Collect When Emacs is Out of Focus

Note: Since Emacs27.1, focus-out-hook is obsolete.

(add-hook 'emacs-startup-hook
          (lambda ()
            (if (boundp 'after-focus-change-function)
                (add-function :after after-focus-change-function
                              (lambda ()
                                (unless (frame-focus-state)
                                  (garbage-collect))))
              (add-hook 'focus-out-hook 'garbage-collect))

Avoid Garbage Collect When Using Minibuffer

(defun gc-minibuffer-setup-hook ()
  (setq gc-cons-threshold better-gc-cons-threshold))

(defun gc-minibuffer-exit-hook ()
  (garbage-collect)
  (setq gc-cons-threshold 800000))

(add-hook 'minibuffer-setup-hook #'gc-minibuffer-setup-hook)
(add-hook 'minibuffer-exit-hook #'gc-minibuffer-exit-hook)))

Load Path

Since all the configuration files are stored in elisp/ folder, they need to be added to load-path on startup.

(defun update-to-load-path (folder)
  "Update FOLDER and its subdirectories to `load-path'."
  (let ((base folder))
    (add-to-list 'load-path base)
    (dolist (f (directory-files base))
      (let ((name (concat base "/" f)))
        (when (and (file-directory-p name)
                   (not (equal f ".."))
                   (not (equal f ".")))
          (add-to-list 'load-path name))))))

(update-to-load-path "~/.emacs.d/elisp")

Define Constants

(defconst *sys/gui*
  (display-graphic-p)
  "Are we running on a GUI Emacs?")

(defconst *sys/win32*
  (eq system-type 'windows-nt)
  "Are we running on a WinTel system?")

(defconst *sys/linux*
  (eq system-type 'gnu/linux)
  "Are we running on a GNU/Linux system?")

(defconst *sys/mac*
  (eq system-type 'darwin)
  "Are we running on a Mac system?")

(defconst *sys/root*
  (string-equal "root" (getenv "USER"))
  "Are you a ROOT user?")

(defconst *rg*
  (executable-find "rg")
  "Do we have ripgrep?")

(defconst *tr*
  (executable-find "tr")
  "Do we have tr?")

(defconst *mvn*
  (executable-find "mvn")
  "Do we have Maven?")

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

(defconst *gcc*
  (executable-find "gcc")
  "Do we have gcc?")

(defconst *curl*
  (executable-find "curl")
  "Do we have curl?")

Package Management

Some packages are disabled with the :disabled tag, because I don't use them very often. They might not work.

Melpa Packages

;; Select the folder to store packages
;; Comment / Uncomment to use desired sites
(setq package-user-dir "~/.emacs.d/elpa"
      package-archives
      '(("gnu"   . "http://elpa.gnu.org/packages/")
        ("melpa" . "https://melpa.org/packages/")
        ("melpa stable" . "http://stable.melpa.org/packages/")
        ("cselpa" . "https://elpa.thecybershadow.net/packages/")))

Load all Melpa packages in elisp/ to load-path directly to reduce startup time.

Non-Melpa Packages

Add packages contained in site-elisp/ to load-path too.

Add Packages Manually from Git

cd site-elisp/
git submodule add https://github.com/foo/bar.git

Verify /.gitmodules file that the newly added package exist.

Update Manually Added Packages

git submodule init
git submodule update

Configure Package Manager

(unless (bound-and-true-p package--initialized) ; To avoid warnings in 27
  (setq package-enable-at-startup nil)          ; To prevent initializing twice
  (package-initialize))

;; set use-package-verbose to t for interpreted .emacs,
;; and to nil for byte-compiled .emacs.elc.
(eval-and-compile
  (setq use-package-verbose (not (bound-and-true-p byte-compile-current-file))))

Use-Package

My Emacs configuration is almost entirely dependant on use-package.

The use-package macro allows you to isolate package configuration in your .emacs file in a way that is both performance-oriented and, well, tidy. I created it because I have over 80 packages that I use in Emacs, and things were getting difficult to manage. Yet with this utility my total load time is around 2 seconds, with no loss of functionality!

;; Install use-package if not installed yet.
(unless (package-installed-p 'use-package)
  (package-refresh-contents)
  (package-install 'use-package))

(eval-and-compile
  (setq use-package-always-ensure t)
  (setq use-package-expand-minimally t)
  (setq use-package-compute-statistics t)
  (setq use-package-enable-imenu-support t))

(eval-when-compile
  (require 'use-package)
  (require 'bind-key))

Auto Package Update

Auto package update automatically updates installed packages if at least auto-package-update-interval days have passed since the last update.

(use-package auto-package-update
  :config
  (setq auto-package-update-interval 7) ;; in days
  (setq auto-package-update-prompt-before-update t)
  (setq auto-package-update-delete-old-versions t)
  (setq auto-package-update-hide-results t)
  (auto-package-update-maybe))

Diminish

Diminish, a feature that removes certain minor modes from mode-line.

(use-package diminish)

GNU Elpa Keyring Update

GNU Elpa Keyring Update, Update Emacs's GPG keyring for GNU ELPA.

The GPG key used to sign the GNU ELPA archives is nearing retirement: it expires this September. Which means that if you don't get the new key before, you won't be able to check the signature of new packages after that date.

(use-package gnu-elpa-keyring-update)

Global Functionalities

User Information

Prerequisite: Please update this file your personal info.

(setq user-full-name "Mingde (Matthew) Zeng")
(setq user-mail-address "matthewzmd@gmail.com")

Bindings

;; Unbind C-z to use as prefix and unbind C-x C-z too
(global-set-key (kbd "C-z") nil)
(global-set-key (kbd "C-x C-z") nil)
;; Use iBuffer instead of Buffer List
(global-set-key (kbd "C-x C-b") #'ibuffer)
;; Truncate lines
(global-set-key (kbd "C-x C-!") #'toggle-truncate-lines)
;; Adjust font size like web browsers
(global-set-key (kbd "C-+") #'text-scale-increase)
(global-set-key (kbd"C--") #'text-scale-decrease)
;; Move up/down paragraph
(global-set-key (kbd "M-n") #'forward-paragraph)
(global-set-key (kbd "M-p") #'backward-paragraph)

;; Some local bindings
(define-key emacs-lisp-mode-map (kbd "<f5>") #'eval-buffer)
(add-hook 'c++-mode-hook (lambda () (local-set-key (kbd "<f5>") #'compile)))
(add-hook 'c-mode-hook (lambda () (local-set-key (kbd "<f5>") #'compile)))

File Management

Dired

Dired, the directory editor.

(use-package dired
  :ensure nil
  :config
  ;; Always delete and copy recursively
  (setq dired-recursive-deletes 'always)
  (setq dired-recursive-copies 'always)

  ;; Auto refresh Dired, but be quiet about it
  (setq global-auto-revert-non-file-buffers t)
  (setq auto-revert-verbose nil)

  ;; Quickly copy/move file in Dired
  (setq dired-dwim-target t)

  ;; Move files to trash when deleting
  (setq delete-by-moving-to-trash t)

  ;; Reuse same dired buffer, so doesn't create new buffer each time
  (put 'dired-find-alternate-file 'disabled nil)
  (add-hook 'dired-mode-hook (lambda () (local-set-key (kbd "<mouse-2>") #'dired-find-alternate-file)))
  (add-hook 'dired-mode-hook (lambda () (local-set-key (kbd "RET") #'dired-find-alternate-file)))
  (add-hook 'dired-mode-hook (lambda () (define-key dired-mode-map (kbd "^")
                                          (lambda () (interactive) (find-alternate-file ".."))))))

Auto Save File and Backup

Set autosave and backup directory.

(make-directory "~/.emacs.d/autosaves" t)
(make-directory "~/.emacs.d/backups" t)
(setq backup-directory-alist '(("." . "~/.emacs.d/backups/"))
      auto-save-file-name-transforms  '((".*" "~/.emacs.d/autosaves/\\1" t))
      delete-old-versions -1
      version-control t
      vc-make-backup-files t)

Rename Both File and Buffer

;; source: http://steve.yegge.googlepages.com/my-dot-emacs-file
(defun rename-file-and-buffer (new-name)
  "Renames both current buffer and file it's visiting to NEW-NAME."
  (interactive "sNew name: ")
  (let ((name (buffer-name))
        (filename (buffer-file-name)))
    (if (not filename)
        (message "Buffer '%s' is not visiting a file!" name)
      (if (get-buffer new-name)
          (message "A buffer named '%s' already exists!" new-name)
        (progn
          (rename-file filename new-name 1)
          (rename-buffer new-name)
          (set-visited-file-name new-name)
          (set-buffer-modified-p nil))))))

File Configs

;; Load the newest version of a file
(setq load-prefer-newer t)

;; Detect external file changes and auto refresh file
(global-auto-revert-mode t)

;; Transparently open compressed files
(auto-compression-mode t)

Search

Prerequisite: Please install ripgrep and add rg to the PATH.

Color-RG

Color-RG, a search and refactoring tool based on ripgrep that is used to search text.

(when *rg*
  (use-package color-rg
    :load-path "~/.emacs.d/site-elisp/color-rg"
    :bind ("C-z s s" . color-rg-search-input)))

Grep-Dired

Grep-Dired, a search and refactoring tool based on ripgrep that is used to search files.

(when *rg*
  (use-package grep-dired
    :load-path "~/.emacs.d/site-elisp/grep-dired"
    :bind
    (("C-z s f" . grep-dired-dwim)
     ("C-z s d" . grep-dired))))

Avy

Avy, a nice way to move around text.

(use-package avy
  :defer t
  :bind
  (("C-;" . avy-goto-char-timer)
   ("C-:" . avy-goto-line))
  :config
  (setq avy-timeout-seconds 0.3)
  (setq avy-style 'pre))

Ivy

Main Ivy

Ivy, a generic completion mechanism for Emacs.

(use-package ivy
  :diminish ivy-mode
  :init (ivy-mode 1)
  :config
  (setq ivy-use-virtual-buffers t)
  (setq ivy-height 10)
  (setq ivy-on-del-error-function nil)
  (setq ivy-magic-slash-non-match-action 'ivy-magic-slash-non-match-create)
  (setq ivy-count-format "【%d/%d】")
  (setq ivy-wrap t))

Amx

Amx, a M-x enhancement tool forked from Smex.

(use-package amx
  :after (:any ivy ido)
  :config (amx-mode))

Counsel

Counsel, a collection of Ivy-enhanced versions of common Emacs commands.

(use-package counsel
  :after ivy
  :diminish counsel-mode
  :init (counsel-mode 1))

Swiper

Swiper, an Ivy-enhanced alternative to isearch.

(use-package swiper
  :bind (("C-M-s" . swiper-isearch)
         ("C-s" . swiper)))

Shell

Shell Hhere

Shell-here, a tool that opens a shell buffer in (or relative to) default-directory.

(use-package shell-here
  :bind ("C-!" . shell-here))

Term Keys

Term-keys, a lossless keyboard input for Emacs in terminal emulators.

(unless *sys/gui*
  (use-package term-keys
    :config (term-keys-mode t)))

Winner

Winner mode restores old window layout.

(use-package winner
  :ensure nil
  :config
  (setq winner-boring-buffers
        '("*Completions*"
          "*Compile-Log*"
          "*inferior-lisp*"
          "*Fuzzy Completions*"
          "*Apropos*"
          "*Help*"
          "*cvs*"
          "*Buffer List*"
          "*Ibuffer*"
          "*esh command on file*"))
  (winner-mode 1))

Which Key

Which Key, a feature that displays the key bindings following the incomplete command.

(use-package which-key
  :diminish
  :init
  (setq which-key-separator " ")
  (setq which-key-prefix-prefix "+")
  :config
  (which-key-mode))

Popup Kill Ring

Popup Kill Ring, a feature that provides the ability to browse Emacs kill ring in autocomplete style popup menu.

(use-package popup-kill-ring
  :bind ("M-y" . popup-kill-ring))

Undo Tree

Undo tree, a feature that provides a visualization of the undos in a file.

(use-package undo-tree
  :defer t
  :diminish undo-tree-mode
  :init (global-undo-tree-mode))

Discover My Major

Discover my major, a feature that discovers key bindings and their meaning for the current Emacs major mode.

(use-package discover-my-major
  :bind (("C-h C-m" . discover-my-major)))

Ace Window

Ace Window, a package for selecting windows to switch to.

(use-package ace-window
  :bind ("C-x C-o" . ace-window))

Configs

Some essential configs that make my life a lot easier.

UTF-8 Coding System

Use UTF-8 as much as possible with unix line endings.

(if (eq system-type 'windows-nt)
    (progn
      (set-clipboard-coding-system 'utf-16-le)
      (set-selection-coding-system 'utf-16-le))
  (set-selection-coding-system 'utf-8))
(prefer-coding-system 'utf-8-unix)
(set-language-environment "UTF-8")
(set-default-coding-systems 'utf-8-unix)
(set-terminal-coding-system 'utf-8-unix)
(set-keyboard-coding-system 'utf-8-unix)
(setq locale-coding-system 'utf-8-unix)
;; Treat clipboard input as UTF-8 string first; compound text next, etc.
(when (display-graphic-p)
  (setq x-select-request-type '(UTF8_STRING COMPOUND_TEXT TEXT STRING)))

Optimize Editing Experience

;; Remove useless whitespace before saving a file
(add-hook 'before-save-hook 'whitespace-cleanup)
(add-hook 'before-save-hook (lambda() (delete-trailing-whitespace)))

;; Make sentences end with a single space
(setq-default sentence-end-double-space nil)

;; Disable Shift mark
(setq shift-select-mode nil)

;; Replace selection on insert
(delete-selection-mode 1)

;; Merge system clipboard with Emacs
(setq-default select-enable-clipboard t)

History

(use-package recentf
  :ensure nil
  :hook (after-init . recentf-mode)
  :init
  (setq recentf-max-saved-items 200)
  (setq recentf-exclude '((expand-file-name package-user-dir)
                          ".cache"
                          ".cask"
                          ".elfeed"
                          "bookmarks"
                          "cache"
                          "ido.*"
                          "persp-confs"
                          "recentf"
                          "undo-tree-hist"
                          "url"
                          "COMMIT_EDITMSG\\'")))

;; When buffer is closed, saves the cursor location
(save-place-mode 1)

;; Set history-length longer
(setq-default history-length 500)

Turn Off Cursor Alarms

(setq ring-bell-function 'ignore)

Show Keystrokes in Progress Instantly

(setq echo-keystrokes 0.1)

Don't Lock Files

(setq-default create-lockfiles nil)

Compilation

Better compilation configurations.

(setq-default compilation-always-kill t) ; kill compilation process before starting another

(setq-default compilation-ask-about-save nil) ; save all buffers on `compile'

(setq-default compilation-scroll-output t)

Move Custom-Set-Variables to Different File

(setq custom-file (concat user-emacs-directory "custom-set-variables.el"))
(load custom-file 'noerror)

Functions

Other important, but longer functions.

Resize Window Width / Height Functions

;; Resizes the window width based on the input
(defun window-resize-width (w)
  "Resizes the window width based on W."
  (interactive (list (if (> (count-windows) 1)
                         (read-number "Set the current window width in [1~9]x10%: ")
                       (error "You need more than 1 window to execute this function!"))))
  (message "%s" w)
  (window-resize nil (- (truncate (* (/ w 10.0) (frame-width))) (window-total-width)) t))

;; Resizes the window height based on the input
(defun window-resize-height (h)
  "Resizes the window height based on H."
  (interactive (list (if (> (count-windows) 1)
                         (read-number "Set the current window height in [1~9]x10%: ")
                       (error "You need more than 1 window to execute this function!"))))
  (message "%s" h)
  (window-resize nil (- (truncate (* (/ h 10.0) (frame-height))) (window-total-height)) nil))

;; Setup shorcuts for window resize width and height
(global-set-key (kbd "C-x C-|") #'window-resize-width)
(global-set-key (kbd "C-x C-_") #'window-resize-height)

Edit This Configuration File Shortcut

(defun edit-configs ()
  "Opens the README.org file."
  (interactive)
  (find-file "~/.emacs.d/init.org"))

(global-set-key (kbd "C-z e") #'edit-configs)

Smarter Move Beginning of Line

Smarter navigation to the beginning of a line by Bozhidar Batsov.

(defun smarter-move-beginning-of-line (arg)
  "Move point back to indentation of beginning of line.

Move point to the first non-whitespace character on this line.
If point is already there, move to the beginning of the line.
Effectively toggle between the first non-whitespace character and
the beginning of the line.

If ARG is not nil or 1, move forward ARG - 1 lines first.    If
point reaches the beginning or end of the buffer, stop there."
  (interactive "^p")
  (setq arg (or arg 1))

  ;; Move lines first
  (when (/= arg 1)
    (let ((line-move-visual nil))
      (forward-line (1- arg))))

  (let ((orig-point (point)))
    (back-to-indentation)
    (when (= orig-point (point))
      (move-beginning-of-line 1))))

;; remap C-a to `smarter-move-beginning-of-line'
(global-set-key [remap move-beginning-of-line] 'smarter-move-beginning-of-line)

Update Org Mode Include Automatically

Update Org Mode INCLUDE Statements Automatically from Artur Malabarba.

(defun save-and-update-includes (&rest ignore)
  "Update the line numbers of #+INCLUDE:s in current buffer.
Only looks at INCLUDEs that have either :range-begin or :range-end.
This function does nothing if not in org-mode, so you can safely
add it to `before-save-hook'."
  (interactive)
  (when (derived-mode-p 'org-mode)
    (save-excursion
      (goto-char (point-min))
      (while (search-forward-regexp
              "^\\s-*#\\+INCLUDE: *\"\\([^\"]+\\)\".*:range-\\(begin\\|end\\)"
              nil 'noerror)
        (let* ((file (expand-file-name (match-string-no-properties 1)))
               lines begin end)
          (forward-line 0)
          (when (looking-at "^.*:range-begin *\"\\([^\"]+\\)\"")
            (setq begin (match-string-no-properties 1)))
          (when (looking-at "^.*:range-end *\"\\([^\"]+\\)\"")
            (setq end (match-string-no-properties 1)))
          (setq lines (decide-line-range file begin end))
          (when lines
            (if (looking-at ".*:lines *\"\\([-0-9]+\\)\"")
                (replace-match lines :fixedcase :literal nil 1)
              (goto-char (line-end-position))
              (insert " :lines \"" lines "\""))))))))

(add-hook 'before-save-hook #'save-and-update-includes)

(defun decide-line-range (file begin end)
  "Visit FILE and decide which lines to include.
BEGIN and END are regexps which define the line range to use."
  (let (l r)
    (save-match-data
      (with-temp-buffer
        (insert-file-contents file)
        (goto-char (point-min))
        (if (null begin)
            (setq l "")
          (search-forward-regexp begin)
          (setq l (line-number-at-pos (match-beginning 0))))
        (if (null end)
            (setq r "")
          (search-forward-regexp end)
          (setq r (1+ (line-number-at-pos (match-end 0)))))
        (format "%s-%s" (+ l 1) (- r 1)))))) ;; Exclude wrapper

MiniBuffer

(defun abort-minibuffer-using-mouse ()
  "Abort the minibuffer when using the mouse."
  (when (and (>= (recursion-depth) 1) (active-minibuffer-window))
    (abort-recursive-edit)))

(add-hook 'mouse-leave-buffer-hook 'abort-minibuffer-using-mouse)

;; keep the point out of the minibuffer
(setq-default minibuffer-prompt-properties '(read-only t point-entered minibuffer-avoid-prompt face minibuffer-prompt))

Duplicate Line

(defun duplicate-line ()
  "Duplicate the current line."
  (interactive)
  (move-beginning-of-line 1)
  (move-beginning-of-line 1)
  (kill-line)
  (yank)
  (open-line 1)
  (forward-line 1)
  (yank))

(global-set-key (kbd "C-z l") #'duplicate-line)

Save All Buffers

(use-package recentf
  :ensure nil
  :hook (after-init . recentf-mode)
  :init
  (setq recentf-max-saved-items 200)
  (setq recentf-exclude '((expand-file-name package-user-dir)
                          ".cache"
                          ".cask"
                          ".elfeed"
                          "bookmarks"
                          "cache"
                          "ido.*"
                          "persp-confs"
                          "recentf"
                          "undo-tree-hist"
                          "url"
                          "COMMIT_EDITMSG\\'")))

;; When buffer is closed, saves the cursor location
(save-place-mode 1)

;; Set history-length longer
(setq-default history-length 500)

Display Line Overlay

(defun display-line-overlay+ (pos str &optional face)
  "Display line at POS as STR with FACE.

FACE defaults to inheriting from default and highlight."
  (let ((ol (save-excursion
              (goto-char pos)
              (make-overlay (line-beginning-position)
                            (line-end-position)))))
    (overlay-put ol 'display str)
    (overlay-put ol 'face
                 (or face '(:background null :inherit highlight)))
    ol))

User Interface Enhancements

All The Icons

All The Icons, a utility package to collect various Icon Fonts. Enable only in GUI Emacs.

Prerequisite: Install all fonts from fonts/all-the-icons-fonts.

(when *sys/gui*
  (use-package all-the-icons))

All The Icons Dired

All The Icons Dired, an icon set for Dired.

(when *sys/gui*
  (use-package all-the-icons-dired
    :after all-the-icons
    :diminish
    :custom-face
    (all-the-icons-dired-dir-face ((t `(:foreground ,(face-background 'default)))))
    :config (add-hook 'dired-mode-hook #'all-the-icons-dired-mode)))

All The Icons Ivy

All The Icons Ivy, an icon set for Ivy.

(when *sys/gui*
  (use-package all-the-icons-ivy
    :after all-the-icons
    :config
    (all-the-icons-ivy-setup)
    (setq all-the-icons-ivy-buffer-commands '())
    (setq all-the-icons-ivy-file-commands
          '(counsel-find-file counsel-file-jump counsel-recentf counsel-projectile-find-file counsel-projectile-find-dir))))

Doom Themes

Doom Themes, an UI plugin and pack of themes.

(when *sys/gui*
  (use-package doom-themes
    :custom-face
    (cursor ((t (:background "BlanchedAlmond"))))
    :config
    ;; flashing mode-line on errors
    (doom-themes-visual-bell-config)
    ;; Corrects (and improves) org-mode's native fontification.
    (doom-themes-org-config)
    (load-theme 'doom-one t)))

Doom Modeline

Doom Modeline, a modeline from DOOM Emacs, but more powerful and faster.

(when *sys/gui*
  (use-package doom-modeline
    :hook (after-init . doom-modeline-mode)
    :config
    ;; Don't compact font caches during GC. Windows Laggy Issue
    (setq inhibit-compacting-font-caches t)
    (setq doom-modeline-minor-modes t)
    ;;(setq doom-modeline-github t) ;; requires ghub package
    (setq doom-modeline-icon t)
    (setq doom-modeline-major-mode-color-icon t)
    (setq doom-modeline-height 15)))

Dashboard

Dashboard

Dashboard, an extensible Emacs startup screen.

Use either KEC_Dark_BK.png or KEC_Light_BK.png depends on the backgrond theme.

(use-package dashboard
  :diminish (dashboard-mode page-break-lines-mode)
  :custom-face
  (dashboard-banner-logo-title ((t (:family "Love LetterTW" :height 115))))
  :config
  (dashboard-setup-startup-hook)
  (setq dashboard-banner-logo-title "Close the world. Open the nExt.")
  (setq dashboard-startup-banner "~/.emacs.d/images/KEC_Dark_BK_Small.png")
  (setq dashboard-items '((recents  . 7)
                          (bookmarks . 5)
                          ;; (projects . 5)
                          (agenda . 5)
                          ))

  ;; Additional Dashboard widgets.
  (defun dashboard-insert-widgets (list-size)
    ;; (insert (format "%d packages loaded in %s.\n" (length package-activated-list) (emacs-init-time)))
    (insert "Navigation: ")
    ;;(insert (make-string (max 0 (floor (/ (- dashboard-banner-length 25) 2))) ?\ ))
    (widget-create 'url-link
                   :tag (propertize "Github" 'face 'font-lock-keyword-face)
                   :help-echo "Open M-EMACS Github"
                   :mouse-face 'highlight
                   "https://github.com/MatthewZMD/.emacs.d")
    (insert " ")
    (widget-create 'push-button
                   :help-echo "Edit M-EMACS configuration"
                   :action (lambda (&rest _) (edit-configs))
                   :mouse-face 'highlight
                   :button-prefix ""
                   :button-suffix ""
                   (propertize "Configuration" 'face 'font-lock-keyword-face)))

  (add-to-list 'dashboard-item-generators  '(buttons . dashboard-insert-widgets))
  (add-to-list 'dashboard-items '(buttons)))

Open Dashboard Function

(defun open-dashboard ()
    "Open the *dashboard* buffer and jump to the first widget."
    (interactive)
    (if (get-buffer dashboard-buffer-name)
        (kill-buffer dashboard-buffer-name))
    (dashboard-insert-startupify-lists)
    (switch-to-buffer dashboard-buffer-name)
    (goto-char (point-min))
    (if (> (length (window-list-1))
           ;; exclude `treemacs' window
           (if (and (fboundp 'treemacs-current-visibility)
                    (eq (treemacs-current-visibility) 'visible)) 2 1))
        (setq dashboard-recover-layout-p t))
    (delete-other-windows))

(global-set-key (kbd "C-z d") #'open-dashboard)

Page Break Lines

Page-break-lines, a feature that displays ugly form feed characters as tidy horizontal rules.

(use-package page-break-lines
  :diminish
  :init (global-page-break-lines-mode))

Fonts

Prepares fonts to use.

Prerequisite: Install Input and Love Letter TW from fonts/.

;; Input Mono, Monaco Style, Line Height 1.3 download from http://input.fontbureau.com/
(defvar fonts '(("Input" . 11) ("SF Mono" . 12) ("Consolas" . 12) ("Love LetterTW" . 12.5))
  "List of fonts and sizes.  The first one available will be used.")

Change Font Function.

(defun change-font ()
  "Documentation."
  (interactive)
  (let* (available-fonts font-name font-size font-setting)
    (dolist (font fonts (setq available-fonts (nreverse available-fonts)))
      (when (member (car font) (font-family-list))
        (push font available-fonts)))

    (if (not available-fonts)
        (message "No fonts from the chosen set are available")
      (if (called-interactively-p 'interactive)
          (let* ((chosen (assoc-string (completing-read "What font to use? " available-fonts nil t) available-fonts)))
            (setq font-name (car chosen) font-size (read-number "Font size: " (cdr chosen))))
        (setq font-name (caar available-fonts) font-size (cdar available-fonts)))

      (setq font-setting (format "%s-%d" font-name font-size))
      (set-frame-font font-setting nil t)
      (add-to-list 'default-frame-alist (cons 'font font-setting)))))

(change-font)

Smooth Scroll

Smoothens Scrolling.

;; Vertical Scroll
(setq scroll-step 1)
(setq scroll-margin 1)
(setq scroll-conservatively 101)
(setq scroll-up-aggressively 0.01)
(setq scroll-down-aggressively 0.01)
(setq auto-window-vscroll nil)
(setq fast-but-imprecise-scrolling nil)
(setq mouse-wheel-scroll-amount '(1 ((shift) . 1)))
(setq mouse-wheel-progressive-speed nil)
;; Horizontal Scroll
(setq hscroll-step 1)
(setq hscroll-margin 1)

Pretty Symbols

Pretty the Symbols.

(global-prettify-symbols-mode 1)
(defun add-pretty-lambda ()
  "Make some word or string show as pretty Unicode symbols. See https://unicodelookup.com for more."
  (setq prettify-symbols-alist
        '(
          ("lambda" . 955)
          ("delta" . 120517)
          ("epsilon" . 120518)
          ("->" . 8594)
          ("<=" . 8804)
          (">=" . 8805)
          )))
(add-hook 'prog-mode-hook 'add-pretty-lambda)
(add-hook 'org-mode-hook 'add-pretty-lambda)

UI Configs

Title Bar

(setq-default frame-title-format '("M-EMACS - " user-login-name "@" system-name " - %b"))

Maximize Frame

(add-to-list 'default-frame-alist '(fullscreen . maximized))

Simplify Yes/No Prompts

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

Disable Splash Screen

(setq inhibit-startup-screen t)
(setq initial-major-mode 'text-mode)
(setq initial-scratch-message "Present Day, Present Time...")

Line Numbers

Display line numbers, and column numbers in modeline.

;; Hook line numbers to only when files are opened
(add-hook 'find-file-hook #'display-line-numbers-mode)
(add-hook 'prog-mode-hook #'display-line-numbers-mode)
;; Display column numbers in modeline
(column-number-mode 1)

General Programming

Magit

Magit, an interface to the version control system Git.

(use-package magit
  :bind ("C-x g" . magit-status))

Projectile

Projectile, a Project Interaction Library for Emacs.

Prerequisite: If using Windows OS, install Gow and add to PATH.

Gow is a lightweight installer that installs useful open source UNIX applications compiled as native win32 binaries. Specifically, tr is needed for Projectile alien indexing.

(use-package projectile
  :bind
  ("C-c p" . projectile-command-map)
  ("C-z i" . projectile-switch-project)
  ("C-z o" . projectile-find-file)
  ("C-z p" . projectile-add-known-project)
  :config
  (projectile-mode 1)
  (setq projectile-completion-system 'ivy)
  (when (and (eq system-type 'windows-nt) *tr*)
    (setq projectile-indexing-method 'alien))
  (add-to-list 'projectile-globally-ignored-directories "node_modules"))

Treemacs

Treemacs, a tree layout file explorer for Emacs.

Treemacs

(use-package treemacs
  :init
  (with-eval-after-load 'winum
    (define-key winum-keymap (kbd "M-0") #'treemacs-select-window))
  :config
  (progn
    (setq treemacs-collapse-dirs
          (if (executable-find "python") 3 0)
          treemacs-deferred-git-apply-delay   0.5
          treemacs-display-in-side-window     t
          treemacs-file-event-delay     5000
          treemacs-file-follow-delay    0.2
          treemacs-follow-after-init    t
          treemacs-follow-recenter-distance   0.1
          treemacs-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-no-png-images        nil
          treemacs-no-delete-other-windows    t
          treemacs-project-follow-cleanup     nil
          treemacs-persist-file   (expand-file-name ".cache/treemacs-persist" user-emacs-directory)
          treemacs-recenter-after-file-follow nil
          treemacs-recenter-after-tag-follow  nil
          treemacs-show-cursor    nil
          treemacs-show-hidden-files    t
          treemacs-silent-filewatch     nil
          treemacs-silent-refresh       nil
          treemacs-sorting        'alphabetic-desc
          treemacs-space-between-root-nodes   t
          treemacs-tag-follow-cleanup   t
          treemacs-tag-follow-delay     1.5
          treemacs-width    35)
    ;; The default width and height of the icons is 22 pixels. If you are
    ;; using a Hi-DPI display, uncomment this to double the icon size.
    ;;(treemacs-resize-icons 44)
    (treemacs-follow-mode t)
    (treemacs-filewatch-mode t)
    (treemacs-fringe-indicator-mode t)
    (pcase (cons (not (null (executable-find "git")))
                 (not (null (executable-find "python3"))))
      (`(t . t) (treemacs-git-mode 'deferred))
      (`(t . _) (treemacs-git-mode 'simple))))
  :bind
  ((:map global-map
         ("M-0"       . treemacs-select-window)
         ("C-x t 1"   . treemacs-delete-other-windows)
         ("C-x t t"   . treemacs)
         ("C-x t B"   . treemacs-bookmark)
         ("C-x t C-t" . treemacs-find-file)
         ("C-x t M-t" . treemacs-find-tag)))
  (:map treemacs-mode-map ("C-p" . treemacs-previous-line)))

Treemacs Magit

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

Treemacs Projectile

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

Company

Company, a text completion framework for Emacs.

(use-package company
  :diminish company-mode
  :defer t
  :init (global-company-mode)
  :config
  (setq company-minimum-prefix-length 1)
  (setq company-tooltip-align-annotations 't)
  (setq company-idle-delay 0)
  (setq company-begin-commands '(self-insert-command))
  (setq company-require-match 'never)
  (setq company-show-numbers t)
  (setq company-global-modes '(not shell-mode))
  (define-key company-mode-map [remap indent-for-tab-command] #'company-indent-or-complete-common))

YASnippet

YASnippet

YASnippet, a programming template system for Emacs. It loads YASnippet Snippets, a collection of yasnippet snippets for many languages.

(use-package yasnippet
  :diminish yas-minor-mode
  :hook (prog-mode . yas-minor-mode)
  :bind
  (("C-c C-n" . yas-expand-from-trigger-key))
  :config
  (use-package yasnippet-snippets)
  (yas-reload-all))

Flycheck

Flycheck, a syntax checking extension.

(use-package flycheck
  :defer t
  :hook (prog-mode . flycheck-mode)
  :config
  (setq flycheck-emacs-lisp-load-path 'inherit)
  (flycheck-add-mode 'javascript-eslint 'js-mode)
  (flycheck-add-mode 'typescript-tslint 'rjsx-mode))

Dumb Jump

Dumb jump, an Emacs "jump to definition" package.

(use-package dumb-jump
  :bind (("M-g o" . dumb-jump-go-other-window)
         ("M-g j" . dumb-jump-go)
         ("M-g i" . dumb-jump-go-prompt)
         ("M-g x" . dumb-jump-go-prefer-external)
         ("M-g z" . dumb-jump-go-prefer-external-other-window))
  :config (setq dumb-jump-selector 'ivy))

Parenthesis

Smartparens

Smartparens, a minor mode for dealing with pairs.

(use-package smartparens
  :hook (prog-mode . smartparens-mode)
  :diminish smartparens-mode
  :bind (:map smartparens-mode-map
              ("C-M-f" . sp-forward-sexp)
              ("C-M-b" . sp-backward-sexp)
              ("C-M-a" . sp-backward-down-sexp)
              ("C-M-e" . sp-up-sexp)
              ("C-M-u" . sp-backward-up-sexp)
              ("C-M-k" . sp-kill-sexp)
              ("C-M-w" . sp-copy-sexp)
              ("M-D" . sp-splice-sexp)
              ("C-M-<backspace>" . sp-splice-sexp-killing-backward)
              ("C-S-<backspace>" . sp-splice-sexp-killing-around)
              ("C-]" . sp-select-next-thing-exchange)
              ("C-M-]" . sp-select-next-thing)
              ("M-i" . sp-change-enclosing))
  :config
  ;; Stop pairing single quotes in elisp
  (sp-local-pair 'emacs-lisp-mode "'" nil :actions nil)
  (sp-local-pair 'org-mode "[" nil :actions nil)
  (setq sp-escape-quotes-after-insert nil)
  ;; Smartparens is broken in `cc-mode' as of Emacs 27. See
  ;; <https://github.com/Fuco1/smartparens/issues/963>.
  (unless (version< emacs-version "27")
    (dolist (fun '(c-electric-paren c-electric-brace))
      (add-to-list 'sp--special-self-insert-commands fun))))

Awesome Pair

Awesome Pair, a feature that provides grammatical parenthesis completion.

(use-package awesome-pair
  :load-path "~/.emacs.d/site-elisp/awesome-pair"
  :bind
  (("C-c C-k" . awesome-pair-kill)
   ("SPC" . awesome-pair-space)
   ("=" . awesome-pair-equal)
   ("M-F" . awesome-pair-jump-right)
   ("M-B" . awesome-pair-jump-left))
  :config
  (add-hook 'prog-mode-hook '(lambda () (awesome-pair-mode 1))))

Delete Block

Delete Block, a feature that deletes block efficiently.

(use-package delete-block
  :load-path "~/.emacs.d/site-elisp/delete-block"
  :bind
  (("M-d" . delete-block-forward)
   ("C-<backspace>" . delete-block-backward)))

Match Parenthesis

Match and automatically pair parenthesis, and show parenthesis even when it went offscreen from Clemens Radermacher.

;; Show matching parenthesis
(show-paren-mode 1)
;; we will call `blink-matching-open` ourselves...
(remove-hook 'post-self-insert-hook
             #'blink-paren-post-self-insert-function)

;; this still needs to be set for `blink-matching-open` to work
(setq blink-matching-paren 'show)
(let ((ov nil)) ; keep track of the overlay
  (advice-add
   #'show-paren-function
   :after
    (defun show-paren--off-screen+ (&rest _args)
      "Display matching line for off-screen paren."
      (when (overlayp ov)
        (delete-overlay ov))
      ;; check if it's appropriate to show match info,
      ;; see `blink-paren-post-self-insert-function'
      (when (and (overlay-buffer show-paren--overlay)
                 (not (or cursor-in-echo-area
                          executing-kbd-macro
                          noninteractive
                          (minibufferp)
                          this-command))
                 (and (not (bobp))
                      (memq (char-syntax (char-before)) '(?\) ?\$)))
                 (= 1 (logand 1 (- (point)
                                   (save-excursion
                                     (forward-char -1)
                                     (skip-syntax-backward "/\\")
                                     (point))))))
        ;; rebind `minibuffer-message' called by
        ;; `blink-matching-open' to handle the overlay display
        (cl-letf (((symbol-function #'minibuffer-message)
                   (lambda (msg &rest args)
                     (let ((msg (apply #'format-message msg args)))
                       (setq ov (display-line-overlay+
                                 (window-start) msg))))))
          (blink-matching-open))))))

Indentation

Highlight Indent Guides, a feature that highlights indentation levels.

(when *sys/gui*
  (use-package highlight-indent-guides
    :diminish
    :hook ((prog-mode web-mode nxml-mode) . highlight-indent-guides-mode)
    :config
    (setq highlight-indent-guides-method 'character)
    (setq highlight-indent-guides-responsive 'top)
    (setq highlight-indent-guides-delay 0)
    (setq highlight-indent-guides-auto-character-face-perc 7)))

Indentation Configuration

(setq-default indent-tabs-mode nil)
(setq-default indent-line-function 'insert-tab)
(setq-default tab-width 4)
(setq-default c-basic-offset 4)
(c-set-offset 'comment-intro 0)
(c-set-offset 'innamespace 0)

Format All

Format all, a feature that lets you auto-format source code.

Prerequisite: Read Supported Languages to see which additional tool you need to install for the specific language.

(use-package format-all
  :bind ("C-z f" . format-all-buffer))

Evil Nerd Commenter

Evil Nerd Commenter, a tool that helps you comment code efficiently.

(use-package evil-nerd-commenter
  :bind
  (("M-;" . evilnc-comment-or-uncomment-lines)
   ("C-z ; p" . evilnc-comment-or-uncomment-paragraphs)
   ("C-z ; c" . evilnc-copy-and-comment-lines)))

Iedit

Iedit, a minor mode that allows editing multiple regions simultaneousy in a buffer or a region.

(use-package iedit
  :bind ("C-z ," . iedit-mode)
  :diminish)

Header

Header2, a support for creation and update of file headers.

(use-package header2
  :load-path "~/.emacs.d/site-elisp/header2"
  :config
  (autoload 'auto-make-header "header2")
  (autoload 'auto-update-file-header "header2")
  (add-hook 'write-file-hooks 'auto-update-file-header)
  (add-hook 'emacs-lisp-mode-hook 'auto-make-header)
  (add-hook 'c-mode-common-hook   'auto-make-header))

Jupyter Notebook

Emacs IPython Notebook, a Jupyter (formerly IPython) client in Emacs.

Usage

  1. Execute M-x ein:run to launch a local Jupyter session.
  2. Login with M-x ein:login to a local or remote session.
  3. Open .ipynb file and press C-c C-o.
(use-package ein
  :disabled
  :defer t)

Programming

Language Server Protocol

LSP Mode

LSP Mode, a client/library for the Language Server Protocol. M-EMACS tries to use lsp-mode whenever possible.

(use-package lsp-mode
  :defer t
  :commands lsp
  :init
  (setq lsp-auto-guess-root nil)
  (setq lsp-prefer-flymake nil) ; Use flycheck instead of flymake
  :bind ("C-z C-f" . lsp-format-buffer)
  :hook ((java-mode . lsp)
         (python-mode . lsp)
         (js2-mode . lsp)
         (typescript-mode . lsp)
         (web-mode . lsp)
         (c-mode . lsp)
         (c++-mode . lsp)
         (objc-mode . lsp)))

LSP UI

LSP UI, provides all the higher level UI modules of lsp-mode, like flycheck support and code lenses.

(use-package lsp-ui
  :after lsp-mode
  :diminish
  :commands lsp-ui-mode
  :custom-face
  (lsp-ui-doc-background ((t (:background nil))))
  (lsp-ui-doc-header ((t (:inherit (font-lock-string-face italic)))))
  :bind (:map lsp-ui-mode-map
              ([remap xref-find-definitions] . lsp-ui-peek-find-definitions)
              ([remap xref-find-references] . lsp-ui-peek-find-references)
              ("C-c u" . lsp-ui-imenu))
  :init
  (setq lsp-ui-doc-enable t
        lsp-ui-doc-header t
        lsp-ui-doc-include-signature t
        lsp-ui-doc-position 'top
        lsp-ui-doc-use-webkit t
        lsp-ui-doc-border (face-foreground 'default)
        lsp-ui-sideline-enable nil
        lsp-ui-sideline-ignore-duplicate t
        lsp-ui-sideline-show-code-actions nil)
  :config
  ;; WORKAROUND Hide mode-line of the lsp-ui-imenu buffer
  ;; https://github.com/emacs-lsp/lsp-ui/issues/243
  (defadvice lsp-ui-imenu (after hide-lsp-ui-imenu-mode-line activate)
    (setq mode-line-format nil)))

Company LSP

Company LSP, a Company completion backend for lsp-mode.

(use-package company-lsp
  :defer t
  :config
  (setq company-lsp-cache-candidates 'auto))

Debug Adapter Protocol

DAP Mode, a client/library for the Debug Adapter Protocol.

(use-package dap-mode
  :disabled
  :after lsp-mode
  :defer t
  :config
  (dap-mode 1)
  (dap-ui-mode 1))

Java

LSP Java

LSP Java, Emacs Java IDE using Eclipse JDT Language Server. Note that this package is dependant on Request.

Prerequisite: Install Maven and add to PATH.

(when *mvn*
  (use-package lsp-java
    :after lsp-mode
    :init
    (use-package request :defer t)
    :config
    (setq
     lsp-java-server-install-dir (expand-file-name "~/.emacs.d/eclipse.jdt.ls/server/")
     lsp-java-workspace-dir (expand-file-name "~/.emacs.d/eclipse.jdt.ls/workspace/"))))

C/C++/Objective C

Prerequisite: Since all completion features are provided by LSP Mode, it needs to setup.

  • Install CMake >= 3.8 for all OS.
  • *nix OS:
    • It is suggested to use CCLS as LSP server. Now build it.
    • Set ccls-executable to the directory where your ccls is built.
  • Windows OS:
    • Install MinGW for Compilation.
    • It is a pain to build CCLS on Windows, install Clangd and add to PATH instead.

Note: Compile using <f5> or compile. The command gcc -o <file>.exe <fileA>.c <fileB>.c ... is to compile C code into <file>.exe.

CC Mode

(use-package cc-mode
  :ensure nil
  :bind (:map c-mode-base-map
              ("<f5>" . compile)))

CCLS

Emacs-CCLS, a client for CCLS, a C/C++/Objective-C language server supporting multi-million line C++ code-bases, powered by libclang.

(unless *sys/win32*
  (use-package ccls
    :defer t
    :hook ((c-mode c++-mode objc-mode) .
           (lambda () (require 'ccls) (lsp)))
    :config
    (setq ccls-executable "~/tools/ccls/Release/ccls")))

Modern C++ Font Lock

Modern CPP Font Lock, font-locking for "Modern C++".

(use-package modern-cpp-font-lock
  :diminish
  :init (modern-c++-font-lock-global-mode t))

Python

Python Configuration

(use-package python
  :after flycheck
  :mode "\\.py\\'"
  :config
  (setq flycheck-python-pycompile-executable "python3")
  (setq python-shell-interpreter "python3"))

LSP Python MS

LSP Python MS, a lsp-mode client leveraging Microsoft's Python Language Server.

(use-package lsp-python-ms
  :after lsp-mode
  :config
  (setq lsp-python-executable-cmd "python3"))

Arduino

Arduino Mode

Arduino mode, a major mode for editing Arduino sketches.

(use-package arduino-mode
  :disabled
  :defer t
  :config
  (add-to-list 'auto-mode-alist '("\\.ino\\'" . arduino-mode))
  (add-to-list 'auto-mode-alist '("\\.pde\\'" . arduino-mode))
  (autoload 'arduino-mode "arduino-mode" "Arduino editing mode." t))

Company Arduino

Company Arduino, a set of configuration to let you auto-completion by using irony-mode, company-irony and company-c-headers on arduino-mode.

(use-package company-arduino
  :disabled
  :defer t
  :config
  (add-hook 'irony-mode-hook 'company-arduino-turn-on)
  ;; Activate irony-mode on arduino-mode
  (add-hook 'arduino-mode-hook 'irony-mode))

Web Development

Prerequisite: Install NodeJS and add to path. Execute following commands to enable LSP for JavaScript/TypeScript/HTML:

npm i -g typescript
npm i -g typescript-language-server
npm i -g vscode-html-languageserver-bin

Web Mode

Web mode, a major mode for editing web templates.

(use-package web-mode
  :custom-face
  (css-selector ((t (:inherit default :foreground "#66CCFF"))))
  (font-lock-comment-face ((t (:foreground "#828282"))))
  :mode
  ("\\.phtml\\'" "\\.tpl\\.php\\'" "\\.[agj]sp\\'" "\\.as[cp]x\\'"
   "\\.erb\\'" "\\.mustache\\'" "\\.djhtml\\'" "\\.[t]?html?\\'"))

JavaScript/TypeScript

JavaScript2 Mode

JS2 mode, a feature that offers improved JavsScript editing mode.

(use-package js2-mode
  :mode "\\.js\\'"
  :interpreter "node")

TypeScript Mode

TypeScript mode, a feature that offers TypeScript support for Emacs.

(use-package typescript-mode
  :mode "\\.ts\\'"
  :commands (typescript-mode))

Emmet

Emmet, a feature that allows writing HTML using CSS selectors along with C-j. See usage for more information.

(use-package emmet-mode
  :hook web-mode
  :config
  (add-hook 'css-mode-hooktype  'emmet-mode)) ;; enable Emmet's css abbreviation

Instant Rename Tag

Instant Rename Tag, a plugin that provides ability to rename html tag pairs instantly.

(use-package instant-rename-tag
  :load-path "~/.emacs.d/site-elisp/instant-rename-tag"
  :bind ("C-z <" . instant-rename-tag))

JSON

JSON Mode,major mode for editing JSON files.

(use-package json-mode
  :mode "\\.json\\'")

Miscellaneous

Org

Org, a Emacs built-in tool for keeping notes, maintaining TODO lists, planning projects, and authoring documents with a fast and effective plain-text system.

Prerequisite: Modify (setq org-agenda-files (list "~/org/agenda/")) to your agenda folder.

(use-package org
  :ensure nil
  :defer t
  :bind
  ("C-c l" . org-store-link)
  ("C-c a" . org-agenda)
  ("C-c c" . org-capture)
  ("C-c b" . org-switch)
  :config
  (setq org-log-done 'time)
  (setq org-export-backends (quote (ascii html icalendar latex md odt)))
  (when (file-directory-p "~/org/agenda/")
    (setq org-agenda-files (list "~/org/agenda/")))
  (setq org-use-speed-commands t)
  (setq org-todo-keywords
        '((sequence "TODO" "IN-PROGRESS" "REVIEW" "|" "DONE"))))

TOC Org

TOC Org generates table of contents for .org files

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

HTMLize

HTMLize, a tool that converts buffer text and decorations to HTML.

(use-package htmlize :defer t)

OX-GFM

OX-GFM, a Github Flavored Markdown exporter for Org Mode.

(use-package ox-gfm :defer t)

Emacs Application Framework

Emacs Application Framework, a development framework that integrates any PyQt program into Emacs.

Prerequisite: Please install python3 and pip3. Then execute below command:

sudo pip install dbus-python PyMuPDF grip qrcode pyqt5 python-xlib
(when *sys/linux*
  (use-package eaf
    :load-path "~/.emacs.d/site-elisp/emacs-application-framework"))

Emacs Web Wowser

EWW, the Emacs Web Wowser.

Set EWW as Default Browser

In Eww, hit & to browse this url system browser

(setq browse-url-browser-function 'eww-browse-url)

Auto-Rename New EWW Buffers

(defun xah-rename-eww-hook ()
  "Rename eww browser's buffer so sites open in new page."
  (rename-buffer "eww" t))
(add-hook 'eww-mode-hook #'xah-rename-eww-hook)

;; C-u M-x eww will force a new eww buffer
(defun force-new-eww-buffer (orig-fun &rest args)
  "ORIG-FUN ARGS When prefix argument is used, a new eww buffer will be created,
  regardless of whether the current buffer is in `eww-mode'."
  (if current-prefix-arg
      (with-temp-buffer
        (apply orig-fun args))
    (apply orig-fun args)))
(advice-add 'eww :around #'force-new-eww-buffer)

PDF Tools

PDF Tools, an Emacs support library for PDF files. It works best on non-Windows OS.

(unless *sys/win32*
  (use-package pdf-tools
    :ensure t
    :config
    (pdf-loader-install)
    (setq TeX-view-program-selection '((output-pdf "pdf-tools")))
    (setq TeX-view-program-list '(("pdf-tools" "TeX-pdf-tools-sync-view")))))

LeetCode

LeetCode, an Emacs LeetCode client. Note that this package is dependant on Request-Deferred and GraphQL.

Prerequisite: Ensure cURL is installed added to PATH. If you are using Windows, it is suggested to use curl provided by Git, therefore add <path to Git>\mingw64\bin to PATH.

(when *curl*
  (use-package leetcode
    :load-path "~/.emacs.d/site-elisp/leetcode.el"
    :commands (leetcode)
    :init
    (use-package request-deferred :defer t)
    (use-package graphql :defer t)
    :config
    ;; (setq request-message-level 'debug)
    ;; (setq request-log-level 'debug)
    (setq leetcode-prefer-language "python3")))

Pinyin

Pyim

Pyim, an Emacs Chinese Pinyin Input.

(use-package pyim
  :config
  (setq default-input-method "pyim")
  (setq pyim-default-scheme 'quanpin)
  (pyim-isearch-mode 1)
  (setq pyim-page-tooltip 'popup)
  (setq pyim-page-length 9)
  ;; 设置 pyim 探针设置,这是 pyim 高级功能设置,可以实现 *无痛* 中英文切换速度 :-)
  ;; 我自己使用的中英文动态切换规则是:
  ;; 1. 光标只有在注释里面时,才可以输入中文。
  ;; 2. 光标前是汉字字符时,才能输入中文。
  ;; 3. 使用 M-j 快捷键,强制将光标前的拼音字符串转换为中文。
  (setq-default pyim-english-input-switch-functions
                '(pyim-probe-dynamic-english
                  pyim-probe-isearch-mode
                  pyim-probe-program-mode
                  pyim-probe-org-structure-template))
  (setq-default pyim-punctuation-half-width-functions
                '(pyim-probe-punctuation-line-beginning
                  pyim-probe-punctuation-after-punctuation))
  :bind
  ("M-j" . pyim-convert-string-at-point))

Pyim Basedict

Pyim Basedict, the default Chinese-Pyim dictionary.

(use-package pyim-basedict
    :after pyim
    :config (pyim-basedict-enable))

Tetris

Although Tetris is part of Emacs, but there still could be some configurations.

(defvar tetris-mode-map
  (make-sparse-keymap 'tetris-mode-map))
(define-key tetris-mode-map (kbd "C-p") 'tetris-rotate-prev)
(define-key tetris-mode-map (kbd "C-n") 'tetris-move-down)
(define-key tetris-mode-map (kbd "C-b") 'tetris-move-left)
(define-key tetris-mode-map (kbd "C-f") 'tetris-move-right)
(define-key tetris-mode-map (kbd "C-SPC") 'tetris-move-bottom)
(defadvice tetris-end-game (around zap-scores activate)
  (save-window-excursion ad-do-it))

Speed Type

Speed type, a game to practice touch/speed typing in Emacs.

(use-package speed-type
  :defer t)

2048 Game

2048 Game, an implementation of 2048 in Emacs.

(use-package 2048-game
  :defer t)

Zone

Zone, a minor-mode 'zones' Emacs out, choosing one of its random modes to obfuscate the current buffer.

(use-package zone
  :ensure nil
  :config
  ;; (zone-when-idle 600) ; in seconds
  (defun zone-choose (pgm)
    "Choose a PGM to run for `zone'."
    (interactive
     (list
      (completing-read
       "Program: "
       (mapcar 'symbol-name zone-programs))))
    (let ((zone-programs (list (intern pgm))))
      (zone))))

About

M-EMACS, a full-featured GNU Emacs configuration distribution

Topics

Resources

License

Code of conduct

Stars

Watchers

Forks

Sponsor this project

 

Packages

No packages published

Contributors 3

  •  
  •  
  •  
0