资源说明:coldnew's emacs config
#+TITLE: coldnew's emacs #+AUTHOR: Yen-Chin, Lee#+email: coldnew.tw at gmail.com #+DESCRIPTION: A literate programming style exposition of my Emacs configuration #+LANGUAGE: en #+STARTUP: overview indent align #+BABEL: :cache yes #+OPTIONS: ^:nil num:nil tags:nil #+SETUPFILE: assets/readtheorg.setup #+LINK: emacs https://www.gnu.org/s/emacs # Badge [[http://www.gnu.org/licenses/gpl-3.0.txt][https://img.shields.io/badge/license-GPL_3-green.svg?dummy]] [[https://travis-ci.org/coldnew/coldnew-emacs][https://travis-ci.org/coldnew/coldnew-emacs.svg?branch=master]] * Introduction This is my emacs configuration, I use ONE single org-mode file to write my emacs config. ** Install emacs My emacs is running under =Mac OSX= and =Gentoo Linux= and I really like them, following are some record for how I installed my emacs. *** Mac OSX In Mac OSX, I use [[http://brew.sh/][homebrew]] to maintain opensource packages, I always install latest version of emacs via following command: #+BEGIN_SRC sh :tangle no # change --HEAD to --devel for current development version brew install emacs --HEAD --use-git-head --with-cocoa --with-gnutls --with-rsvg --with-imagemagick brew linkapps #+END_SRC *** Gentoo Linux [[https://www.gentoo.org/][Gentoo Linux]] is the best linux distrobution I ever used and it's really easy to install latest apps. #+BEGIN_SRC sh :tangle no USE="X gtk3 inotify xft imagemagick" emerge app-editors/emacs #+END_SRC *** Building with script My emacs configuration already shipped an update-to-date version of emacs based on git submodule, if your system can build emacs from source you can use my [[file:scripts/build-emacs.sh]] script to build latested emacs. #+BEGIN_EXAMPLE ./scripts/build-emacs.sh #+END_EXAMPLE Note that if your are building under =Mac OSX=, don't forget to install xcode tools: #+BEGIN_SRC sh :tangle no xcode-select --install #+END_SRC ** Install or testing this config - First use git to download whole repo : git clone https://github.com/coldnew/coldnew-emacs.git - Then use git submodule to download the spacemacs #+BEGIN_EXAMPLE git submodule update --init --recursive #+END_EXAMPLE - To generate the =init.el=, jut type : make - If you do not put this repo on =~/.emacs.d=, you need to use following command to start emacs : emacs -q -l ~/coldnew-emacs/init.el ** Packages need to be installed in system (Optional) Some extra packages need to be installed in the system manually. These packages are =optional= but can make this configuration work more nicely. *** Mac OSX In Mac OSX, I use [[http://brew.sh/][homebrew]] to install opensource packages. #+BEGIN_SRC sh :tangle no :noweb yes #brew install fasd #brew install aspell --with-lang-en < > #+END_SRC *** Gentoo Linux In Gentoo Linux, don't forget to enable ~USE=emacs~ to make Gentoo auto install emacs-related packages. #+BEGIN_SRC sh :tangle no :noweb yes #emerge app-shells/fasd #emerge app-shells/aspell < > #+END_SRC *** All platform Some package like =npm= use the same rule to install in any platform, here list what I need to install. #+BEGIN_SRC sh :tangle no :noweb yes < > #+END_SRC * Early Initialize :init:early: Since Emacs 27, we can add some setup in =~/.emacs.d/early-init.el= , these setup will be loadded before emacs startup. #+begin_src emacs-lisp :noweb no-export :exports code :padline no :tangle early-init.el ;; early-init.el --- -*- lexical-binding: t; -*- < > (provide 'early-init) ;;; early-init.el ends here #+end_src ** Disable native-compilation for some packages Adding regexes to `comp-deferred-compilation-deny-list' to make some packages not build by native-compilation when enabled. Here I just disable native-compile auto loads. There's something wrong with them. #+begin_src emacs-lisp :tangle no :noweb-ref early-init (with-eval-after-load 'comp (setq-default comp-deferred-compilation-deny-list '("\\(?:[^z-a]*-autoloads\\.el$\\)"))) #+end_src ** Prevent native-compilation warning window popup native-compilation will asyn report warning or error info, it's so annoying, set it to silent mode so these warning will just logging but not pop up the window. #+begin_src emacs-lisp :tangle no :noweb-ref early-init (with-eval-after-load 'comp (setq native-comp-async-report-warnings-errors 'silent)) #+end_src ** Defer garbage collection further back in the startup process #+BEGIN_SRC emacs-lisp :tangle no :noweb-ref early-init (setq gc-cons-threshold most-positive-fixnum) #+END_SRC ** Prevent the glimpse of un-styled Emacs by disabling these UI elements early. #+BEGIN_SRC emacs-lisp :tangle no :noweb-ref early-init (push '(menu-bar-lines . 0) default-frame-alist) (push '(tool-bar-lines . 0) default-frame-alist) (push '(vertical-scroll-bars) default-frame-alist) #+END_SRC ** Prevent package.el to load packages prior to init.el loading We plain to handle our package initialization in our configs, we must prevent Emacs from doing it at early stage. #+BEGIN_SRC emacs-lisp :tangle no :noweb-ref early-init (setq package-enable-at-startup nil) #+END_SRC ** Allow loading from the package cache #+BEGIN_SRC emacs-lisp :tangle no :noweb-ref early-init (when (>= emacs-major-version 27) (setq-default package-quickstart t)) #+END_SRC ** Do not resize the frame at this early stage. #+BEGIN_SRC emacs-lisp :tangle no :noweb-ref early-init (setq frame-inhibit-implied-resize t) #+END_SRC * Initialize Emacs :init: There are some configurations I need to put at the beginning of the emacs config. These configurations are derived from my original init.el file. ** Use lexical binding For some of my functions, and general coolness, =lexical binding= is a must. Without it, closures cannot be made for example. This line needs to appear at the beginning of the file to work. Just to keep things looking nice I put it at the beginning of the file. #+BEGIN_SRC emacs-lisp :padline no ;; -*- lexical-binding: t -*- #+END_SRC ** Make Emacs-26 compatible with Emacs-25 Emacs 26 introduce new =switch= bytecode which not contains in emacs-25, disable it so I can test both emacs-25 and emacs-26. #+BEGIN_SRC emacs-lisp (setq byte-compile-cond-use-jump-table nil) #+END_SRC ** Use Common Lisp Extension Some of my function may need the Common Lisp Extension, let's import libraries first. #+BEGIN_SRC emacs-lisp (require 'cl-lib) ; built-in #+END_SRC ** Load extra builtin library Add some extry buildin library I will use in my config file. #+BEGIN_SRC emacs-lisp (require 'find-lisp) #+END_SRC ** Prevent load outdated .elc files Since emacs 24.4, new option =load-prefer-newer= has been introduce, which make me never accidentally using outdated compiled files. #+BEGIN_SRC emacs-lisp (setq load-prefer-newer t) #+END_SRC ** Setup user-emacs-directory variable :variable: In this configuration, =user-emacs-directory= always refer to the emacs configuration's init.el parent directory. #+BEGIN_SRC emacs-lisp ;; We set `user-emacs-directory' here so we can use command-line ;; switch different emacs configuration like following: ;; ;; emacs -q -l ~/coldnew-spacemacs/init.el (defconst user-emacs-directory (file-name-directory (or load-file-name (buffer-file-name))) "My emacs config directory.") #+END_SRC ** Setup user-cache-directory variable :variable: Setup the cache directory to store some cache content. #+BEGIN_SRC emacs-lisp (defconst user-cache-directory (file-name-as-directory (concat user-emacs-directory ".cache")) "My emacs storage area for persistent files.") ;; create the `user-cache-directory' if not exists (make-directory user-cache-directory t) #+END_SRC ** Setup user-modules-directory variable :variable: Setup the modules directory to store some submodules and extra packages. #+BEGIN_SRC emacs-lisp (defconst user-modules-directory (file-name-as-directory (concat user-emacs-directory "modules")) "My emacs storage area for modules.") #+END_SRC ** Setup user-ramdisk-directory variable :variable: I specify a ramdisk path to make my emacs can save som temporary file to it. The ramdisk path should be =~/ramdisk=, if the directory not found, use =/tmp= as fallback. #+BEGIN_SRC emacs-lisp (defconst user-ramdisk-directory (let ( (user-ramdisk ; ~/ramdisk/ (concat (getenv "HOME") "/ramdisk/"))) ;; if ~/ramdisk/ exist, use it (if (file-exists-p user-ramdisk) user-ramdisk ;; fallcack to system default ramdisk dir temporary-file-directory)) "My ramdisk path in system.") #+END_SRC ** Setup Load path The variable =load-path= lists all the directories where Emacs should look for emacs-lisp files. Following are my method to add directories to load-path ~recursively~, this function also create directory to prevent directory not exist. If you don't have any local elisp and all packages is maintain by cask or elpa or spacemacs, you can skip following code. #+BEGIN_SRC emacs-lisp (eval-and-compile ;; Add directories to emacs's `load-path' recursively. ;; if path does not exist, try to create directory. (let* ((my-lisp-dir (list (concat user-emacs-directory "elpa/") ; package installed by package.el (concat user-emacs-directory "local-lisp/") ; local lisp I used (concat user-emacs-directory "styles/"))) ; themes I used (sys-lisp-dir (cl-ecase system-type ; add some system site-lisp to load-path ((darwin) '("/usr/local/share/emacs/site-lisp/")) ((gnu/linux) '("/usr/share/emacs/site-lisp/")) (t nil))) ; FIXME: Add more platform support (lisp-dir (append my-lisp-dir sys-lisp-dir))) (dolist (lisp-path lisp-dir) (when (not (file-exists-p lisp-path)) (make-directory lisp-path t)) (let* ((default-directory lisp-path)) (setq load-path (append (let ((load-path (copy-sequence load-path))) (append (copy-sequence (normal-top-level-add-to-load-path '("."))) (normal-top-level-add-subdirs-to-load-path))) load-path)))))) #+END_SRC ** Under Mac OSX use Command key as ALT Under Mac OSX, I always bind =Caps lock= as Control key, and make the =Command= key as =ALT= key like I done in Linux. The =Option= key will be setup as =Super=. I also disable some keys like =⌘-h= bypass to system in emacs-mac port. #+BEGIN_SRC emacs-lisp (when (eq system-type 'darwin) (setq-default mac-option-modifier 'super) (setq-default mac-command-modifier 'meta)) #+END_SRC ** Save custom-file as cache Most of my config is written in this file, it's no need to tracking the emacs's custom-setting. I move the file to cache-dir and make git ignore it. #+BEGIN_SRC emacs-lisp (setq-default custom-file (concat user-cache-directory "custom.el")) ;; load custom-file only when file exist (when (file-exists-p custom-file) (load-file custom-file)) #+END_SRC ** Loading Modules I think I'll write some dynamic module extension, which will save to =~/.emacs.d/modules=, use a helper script to help me load them. #+BEGIN_SRC emacs-lisp ;; load the `load-modules.el' file which help me load external modulept (let ((script (concat user-modules-directory "load-modules.el"))) (when (file-exists-p script) (load script))) #+END_SRC ** Startup emacs server Only start server mode if I'm not root #+BEGIN_SRC emacs-lisp (unless (string-equal "root" (getenv "USER")) (require 'server) (when (fboundp 'server-running-p) (unless (server-running-p) (server-start)))) #+END_SRC ** Setup backup files By default Emacs saves =BackupFiles= under the original name with a tilde =~= appended. Example: Editing README will result in README and README~ in the same directory. This is primitive and boring. I save my backup files to =~/.emacs.d/.cache/backup= and since is always ignore by version control system, it's a nice place to store backup files. #+BEGIN_SRC emacs-lisp (let ((backup-dir (concat user-cache-directory "backup"))) ;; Move backup file to `~/.emacs.d/.cache/backup' (setq backup-directory-alist `(("." . ,backup-dir))) ;; Makesure backup directory exist (when (not (file-exists-p backup-dir)) (make-directory backup-dir t))) #+END_SRC Also setup some backup settings. #+BEGIN_SRC emacs-lisp (setq delete-by-moving-to-trash nil) (setq version-control t) (setq kept-old-versions 10) (setq kept-new-versions 20) (setq delete-old-versions t) (setq backup-by-copying t) #+END_SRC ** Disable some default stuff Some emacs feature is not really useful *** Turn-off Alarm Bell #+BEGIN_SRC emacs-lisp (setq ring-bell-function #'ignore) #+END_SRC *** Clean scratch buffer messages Leave me a clean **scratch** buffer and I'll be more happy :) #+BEGIN_SRC emacs-lisp (setq initial-scratch-message "") #+END_SRC *** Use visible bell instead of buzzer #+BEGIN_SRC emacs-lisp (setq visible-bell t) #+END_SRC *** Ask for y or n, not yes or no Emacs starts out asking for you to type yes or no with most important questions. Just let me use =y= or =n= with no =RET= required an I'm quite happy. #+BEGIN_SRC emacs-lisp (defalias 'yes-or-no-p 'y-or-n-p) #+END_SRC ** Maximized window after emacs start #+BEGIN_SRC emacs-lisp (modify-all-frames-parameters '((fullscreen . maximized))) #+END_SRC * Personal Information :personal: It's useful to have some basic personal information. #+BEGIN_SRC emacs-lisp (setq user-full-name "Yen-Chin, Lee") (setq user-mail-address "coldnew.tw@gmail.com") #+END_SRC Some of my password stored in a secret file with gnupg encrypt, I add this function here so I can inject some emacs-command which hass password/account setting. #+BEGIN_SRC emacs-lisp (defun my-load-secret () "Load my secret setting include password... etc." (let ((secret "~/.secret.el.gpg")) (when (file-exists-p secret) (load-file secret)))) #+END_SRC * Package Management The main package manager I use is emacs's =package.el=, it's really nice and easy to use. ** Add my extra package list [[http://melpa.org][melpa]] contains many community packages that not contribute to emacs's elpa, we add it here. #+BEGIN_SRC emacs-lisp (eval-and-compile (require 'package) ; built-in ;; melpa (add-to-list 'package-archives '("melpa" . "https://melpa.org/packages/") t) ;; For important compatibility libraries like cl-lib (when (< emacs-major-version 24) (add-to-list 'package-archives '("gnu" . "https://elpa.gnu.org/packages/")))) #+END_SRC ** Initialize package.el Before we start to use =package.el=, we need to initialize it first. #+BEGIN_SRC emacs-lisp ;; This must come before configurations of installed packages. ;; Don't delete this line. If you don't want it, just comment it out by adding a ;; semicolon to the start of the line. You may delete these explanatory ;; comments. (eval-and-compile (when (< emacs-major-version 27) (package-initialize))) #+END_SRC ** Install 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! GitHub: https://github.com/jwiegley/use-package #+BEGIN_SRC emacs-lisp (eval-and-compile (unless (package-installed-p 'use-package) (package-refresh-contents) (package-install 'use-package))) ; Installed by packages.el #+END_SRC use-package now can only need once, just add it to compile time #+BEGIN_SRC emacs-lisp (eval-when-compile (require 'use-package)) #+END_SRC You can setup =use-package-always-ensure= variable to =t= if you want to make =use-package= auto install packages. However, since we need to initialize =spacemacs= first, we need to setup this variable after spacemacs init. #+BEGIN_SRC emacs-lisp :tangle no :noweb-ref spacemacs-later-init ;; make `use-package' auto install non-installed packages. (when (require 'use-package-ensure) (setq use-package-always-ensure t)) #+END_SRC Report details about loading and configuration. #+BEGIN_SRC emacs-lisp (setq use-package-verbose t) #+END_SRC The =:ensure-system-package= keyword allows you to ensure system binaries exist alongside your package declarations. We need to install =use-package-ensure-system-package= first. #+BEGIN_SRC emacs-lisp (use-package use-package-ensure-system-package :ensure t :define (use-package-ensure-system-package-exists?)) #+END_SRC ** Install straight straight.el is next-generation, purely functional package manager for the Emacs hacker. It can integrated with [[https://github.com/jwiegley/use-package][use-package]] and install some packages from fork. GitHub: https://github.com/raxod502/straight.el #+BEGIN_SRC emacs-lisp (let ((bootstrap-file (expand-file-name "straight/repos/straight.el/bootstrap.el" user-emacs-directory))) (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)) #+END_SRC ** Install paradox Project for modernizing Emacs' Package Menu. With improved appearance, mode-line information. Github integration, customizability, asynchronous upgrading, and more. GitHub: https://github.com/Malabarba/paradox #+BEGIN_SRC emacs-lisp (use-package paradox :ensure t :commands (paradox-enable) :hook (after-init . paradox-enable) :init (setq paradox-execute-asynchronously t paradox-spinner-type 'progress-bar paradox-github-token t paradox-display-star-count nil)) #+END_SRC ** Install some common libraries Some common libraries I'll use in my personal's command or anything else. #+BEGIN_SRC emacs-lisp (use-package f :ensure t) (use-package s :ensure t) (use-package dash :ensure t) (use-package htmlize :ensure t) (use-package async :ensure t) #+END_SRC * Languages and Encodings Add UTF8 at the front of the priority list for automatic detection. #+BEGIN_SRC emacs-lisp (prefer-coding-system 'utf-8) #+END_SRC Set up multilingual environment to use UTF-8. #+BEGIN_SRC emacs-lisp (set-language-environment "UTF-8") #+END_SRC Set default value of various coding systems to UTF-8. #+BEGIN_SRC emacs-lisp (set-default-coding-systems 'utf-8) #+END_SRC Use =C= as locale for display time info (Actually it will display English). #+BEGIN_SRC emacs-lisp (setq system-time-locale "C") #+END_SRC * Built-in Packages Some buildin packages need to add extra setups for my emacs setting. Most of them are the cache file, I'll move them to =~/.emacs.d/.cache= directory. ** abbrev #+BEGIN_SRC emacs-lisp (eval-after-load 'bookmark '(progn (setq abbrev-file-name (concat user-cache-directory "abbrev_defs")))) #+END_SRC ** eshell Move eshell cache dir to =~/.emacs.d/.cache/eshell= #+BEGIN_SRC emacs-lisp (eval-when-compile (defvar eshell-directory-name)) ; defined in esh-mode.el (with-eval-after-load 'esh-mode (setq-default eshell-directory-name (concat user-cache-directory "eshell"))) (with-eval-after-load 'em-hist (setq-default eshell-history-file-name (expand-file-name "history" eshell-directory-name))) #+END_SRC ** bookmark #+BEGIN_SRC emacs-lisp (eval-after-load 'bookmark '(progn (setq-default bookmark-default-file (concat user-cache-directory "bookmarks")))) #+END_SRC ** idlwave Major mode for editing IDL source files. #+BEGIN_SRC emacs-lisp (eval-after-load 'idlwave '(progn (setq-default idlwave-config-directory (concat user-cache-directory "idlwave")))) #+END_SRC ** srecode #+BEGIN_SRC emacs-lisp ;; change srecode cache file path (eval-after-load 'srecode '(progn (setq-default srecode-map-save-file (concat user-cache-directory "srecode-map.el")))) #+END_SRC ** request #+BEGIN_SRC emacs-lisp (eval-after-load 'request '(progn (setq-default request-storage-directory (concat user-cache-directory "request")))) #+END_SRC ** nsm #+BEGIN_SRC emacs-lisp (eval-after-load 'nsm '(progn (setq-default nsm-settings-file (concat user-cache-directory "network-security.data")))) #+END_SRC ** url #+BEGIN_SRC emacs-lisp (eval-after-load 'url '(progn (setq url-configuration-directory (file-name-as-directory (concat user-cache-directory "url"))))) #+END_SRC ** startup #+BEGIN_SRC emacs-lisp ;; NOTE: ;; `auto-save-list-file-prefix' defined in startup.el, but ;; startup.el doesn't have provide pacage name (provide 'startup) ;; (setq-default auto-save-list-file-prefix (cond ((eq system-type 'ms-dos) ;; MS-DOS cannot have initial dot, and allows only 8.3 names (file-name-as-directory (concat user-cache-directory "auto-save.list/_saves-"))) (t (file-name-as-directory (concat user-cache-directory "auto-save-list/.saves-"))))) #+END_SRC * External Packages :packages: Most of emacs packages do not need many configs or just provide commands/functions to use, I put them here. ** ag [[https://github.com/Wilfred/ag.el][ag.el]] allows you to search using [[https://github.com/ggreer/the_silver_searcher][the_silver_searcher]] from inside Emacs. You can filter by file type, edit results inline, or find files. GitHub: https://github.com/Wilfred/ag.el #+BEGIN_SRC emacs-lisp (use-package ag :ensure t ;; only use this package when `the_silver_seacher' install in system. :ensure-system-package ag) #+END_SRC *** Install System packages To use [[https://github.com/Wilfred/ag.el][ag.el]] we also need to install [[https://github.com/ggreer/the_silver_searcher][the_silver_searcher]] in system. **** Mac OSX It's recommand to use [[http://brew.sh/][homebrew]] to install [[https://github.com/ggreer/the_silver_searcher][the_silver_searcher]] under Mac OSX. #+BEGIN_SRC sh :tangle no :noweb-ref install-in-macosx brew install the_silver_searcher #+END_SRC **** Gentoo Linux If you use Gentoo Linux, you can use portage to install it. #+BEGIN_SRC emacs-lisp :tangle no :noweb-ref install-in-gentoo emerge sys-apps/the_silver_searcher #+END_SRC ** avy =avy= is a GNU Emacs package for jumping to visible text using a char-based decision tree. See also [[https://github.com/winterTTr/ace-jump-mode][ace-jump-mode]] and [[https://github.com/Lokaltog/vim-easymotion][vim-easymotion]] - =avy= uses the same idea. GitHub: https://github.com/abo-abo/avy #+BEGIN_SRC emacs-lisp (use-package avy :ensure t) #+END_SRC ** discover-my-major :command: [[https://github.com/steckerhalter/discover-my-major][discover-my-major]] make you discover key bindings and their meaning for the current Emacs major mode. GitHub: https://github.com/steckerhalter/discover-my-major #+BEGIN_SRC emacs-lisp (use-package discover-my-major :defer 2 ; Install pkg if not exist after 2 sec idle time :commands (discover-my-major)) #+END_SRC ** doxymacs Doxygen is a system for extracting documentation from source code. It supports a variety of programming languages, human languages and output formats. You can find it at http://www.doxygen.org. [[http://doxymacs.sourceforge.net/][doxymacs]] is emacs's wrapper for Doxygen. #+BEGIN_SRC emacs-lisp (when (require 'doxymacs nil 'noerror) (add-hook 'prog-mode-hook '(lambda () (doxymacs-mode)))) #+END_SRC *** Install System Packages To use [[http://doxymacs.sourceforge.net/][doxymacs]] we also need to install it in system manually. **** Mac OSX For Mac OSX, just type #+BEGIN_SRC sh :tangle no :noweb-ref install-in-macosx brew install doxymacs #+END_SRC **** Gentoo Linux If you use Gentoo Linux, you can use following command to install this package #+BEGIN_SRC emacs-lisp :tangle no :noweb-ref install-in-gentoo emerge app-shells/doxymacs #+END_SRC ** esup Benchmark Emacs Startup time without ever leaving your Emacs. GitHub: https://github.com/jschaf/esup #+BEGIN_SRC emacs-lisp (use-package esup :ensure t :commands (esup) :init ;; Work around a bug where esup tries to step into the byte-compiled ;; version of `cl-lib', and fails horribly. ;; see: ;; https://github.com/jschaf/esup/issues/54#issuecomment-651247749 (setq esup-depth 0)) #+END_SRC ** exec-path-from-shell [[https://github.com/purcell/exec-path-from-shell][exec-path-from-shell]] is A GNU Emacs library to ensure environment variables inside Emacs look the same as in the user's shell. Ever find that a command works in your shell, but not in Emacs? This happens a lot on OS X, where an Emacs instance started from the GUI inherits a default set of environment variables. This library works solves this problem by copying important environment variables from the user's shell: it works by asking your shell to print out the variables of interest, then copying them into the Emacs environment. GitHub: https://github.com/purcell/exec-path-from-shell #+BEGIN_SRC emacs-lisp (use-package exec-path-from-shell :ensure t :if (memq window-system '(mac ns x)) :init (exec-path-from-shell-initialize)) #+END_SRC ** expand-region :keybinding: Expand region increases the selected region by semantic units. Just keep pressing the key until it selects what you want. GitHub: https://github.com/magnars/expand-region.el #+BEGIN_SRC emacs-lisp (use-package expand-region :ensure t :bind (("M-v" . er/expand-region))) #+END_SRC ** fancy-narrow Emacs package to immitate [[http://bruce-connor.github.io/emacs-online-documentation/Fun%252Fnarrow-to-region.html][narrow-to-region]] with more eye-candy. GitHub: https://github.com/Malabarba/fancy-narrow #+BEGIN_SRC emacs-lisp (use-package fancy-narrow :ensure t) #+END_SRC ** focus Focus provides =focus-mode= that dims the text of surrounding sections, similar to [[https://ia.net/writer][iA Writer's]] Focus Mode. GitHub: https://github.com/larstvei/Focus #+BEGIN_SRC emacs-lisp (use-package focus :ensure t) #+END_SRC ** fontawesome Emacs [[http://fortawesome.github.io/Font-Awesome/][fontawesome]] utility. GitHub: https://github.com/syohex/emacs-fontawesome #+BEGIN_SRC emacs-lisp (use-package fontawesome :ensure t) #+END_SRC ** google-translate This package allows to translate the strings using Google Translate service directly from GNU Emacs. GitHub: https://github.com/atykhonov/google-translate #+BEGIN_SRC emacs-lisp (use-package google-translate :ensure t) #+END_SRC ** goto-last-change Move point through buffer-undo-list positions. GitHub: https://github.com/camdez/goto-last-change.el #+BEGIN_SRC emacs-lisp (use-package goto-last-change :ensure t) #+END_SRC ** howdoi :command: [[https://github.com/atykhonov/emacs-howdoi][howdoi]] is a way to query Stack Overflow directly from the Emacs and get back the most upvoted answer to the first question that comes up for that query. GitHub: https://github.com/atykhonov/emacs-howdoi #+BEGIN_SRC emacs-lisp (use-package howdoi :defer 2 :commands (howdoi-query howdoi-query-line-at-point)) #+END_SRC ** hungry-delete [[https://github.com/nflath/hungry-delete][hungry-delete]] borrows hungry deletion from =cc-mode=, which will causes deletion to delete all whitespace in the direction you are deleting. #+BEGIN_SRC emacs-lisp (use-package hungry-delete :ensure t :config (global-hungry-delete-mode)) #+END_SRC ** iedit :keybinding: [[https://github.com/victorhge/iedit][iedit]] let you edit multiple regions in the same way simultaneously. GitHub: https://github.com/victorhge/iedit #+BEGIN_SRC emacs-lisp (use-package iedit :ensure t :bind (("C-;" . iedit-mode))) #+END_SRC ** link-hint =link-hint.el= is inspired by the link hinting functionality in vim-like browsers and browser plugins such as pentadactyl. It provides commands for using avy to open or copy "links." GitHub: https://github.com/noctuid/link-hint.el #+BEGIN_SRC emacs-lisp (use-package link-hint :ensure t) #+END_SRC ** manage-minor-mode [[https://github.com/ShingoFukuyama/manage-minor-mode][manage-minor-mode]] let you manage your minor-mode on the dedicated interface buffer. #+BEGIN_SRC emacs-lisp (use-package manage-minor-mode :ensure t) #+END_SRC ** mwim :keybinding: This Emacs package provides commands for moving to the beginning/end of code or line. GitHub: https://github.com/alezost/mwim.el #+BEGIN_SRC emacs-lisp (use-package mwim :ensure t :bind (("C-a" . mwim-beginning-of-code-or-line) ("C-e" . mwim-end-of-code-or-line))) #+END_SRC ** pangu-spacing [[https://github.com/coldnew/pangu-spacing][pangu-spcing]] is an minor-mode to auto add =space= between Chinese and English characters. Note that these white-space characters are not really added to the contents, it just like to do so. GitHub: https://github.com/coldnew/pangu-spacing #+BEGIN_SRC emacs-lisp (use-package pangu-spacing :ensure t :commands (global-pangu-spacing-mode) :config ;; start pangu-spacing globally (global-pangu-spacing-mode 1) ;; Always insert `real' space in org-mode. (add-hook 'org-mode-hook (lambda () (set (make-local-variable 'pangu-spacing-real-insert-separtor) t)))) #+END_SRC ** password-generator [[https://github.com/zargener/emacs-password-genarator][password-generator]] provides simple functions to create passwords and insert them inside buffer immediately. GitHub: https://github.com/zargener/emacs-password-genarator #+BEGIN_SRC emacs-lisp (use-package password-generator :ensure t) #+END_SRC ** rainbow-mode [[https://julien.danjou.info/projects/emacs-packages][rainbow-mode]] s a minor mode for Emacs which displays strings representing colors with the color they represent as background. #+BEGIN_SRC emacs-lisp (use-package rainbow-mode :ensure t) #+END_SRC ** smartparens Smartparens is a minor mode for dealing with pairs in Emacs. GitHub: https://github.com/Fuco1/smartparens #+BEGIN_SRC emacs-lisp (use-package smartparens :ensure t :commands (smartparens-mode) :config (smartparens-mode 1)) #+END_SRC ** sx [[https://github.com/vermiculus/sx.el/][SX]] is a full featured Stack Exchange mode for GNU Emacs 24+. Using the official API, it provides a versatile experience for the Stack Exchange network within Emacs itself. #+BEGIN_SRC emacs-lisp (use-package sx :ensure t) #+END_SRC ** tldr :command: tldr is a collection of simplified and community-driven man pages. GitHub: https://github.com/kuanyui/tldr.el #+BEGIN_SRC emacs-lisp (use-package tldr :defer 2 :commands (tldr) :config (setq tldr-directory-path (concat user-cache-directory "tldr/")) (setq tldr-saved-zip-path (concat user-cache-directory "tldr-source.zip"))) #+END_SRC ** url-shortener This package can convert long url to tiny url and expand tiny url to long url ,support: - bit.ly - goo.gl - dwz.cn - 126.am GitHub: https://github.com/yuyang0/url-shortener #+BEGIN_SRC emacs-lisp (use-package url-shortener :ensure t) #+END_SRC ** verify-url [[https://github.com/lujun9972/verify-url][verify-url]] is a little tool that used to find out invalid urls in the buffer or region. Use =M-x verify-url= to find invalid urls in current buffer. After executed command, you can use =verify-url/next-invalid-url= to goto next invalid-url or =verify-url/previous-invalid-url= to goto previous one. GitHub: https://github.com/lujun9972/verify-url #+BEGIN_SRC emacs-lisp (use-package verify-url :defer 2 :commands (verify-url)) #+END_SRC ** visual-regexp visual-regexp for Emacs is like replace-regexp, but with live visual feedback directly in the buffer. Check out [[https://github.com/benma/visual-regexp-steroids.el/][visual-regexp-steroids]] if you want to use modern regular expressions instead of Emacs-style regular expressions. GitHub: https://github.com/benma/visual-regexp.el #+BEGIN_SRC emacs-lisp (use-package visual-regexp :ensure t) #+END_SRC ** webpaste webpaste.el allows to paste whole buffers or parts of buffers to pastebin-like services. It supports more than one service and will failover if one service fails. More services can easily be added over time and prefered services can easily be configured. Supported platform: - [X] ix.io - [X] dpaste.com - [X] sprunge.us - [X] dpaste.de - [ ] paste.pound-python.org - [ ] paste.debian.net - [ ] bpaste.net GitHub: https://github.com/etu/webpaste.el #+BEGIN_SRC emacs-lisp (use-package webpaste :ensure t) #+END_SRC ** which-key which-key is a minor mode for Emacs that displays the key bindings following your currently entered incomplete command (a prefix) in a popup. For example, after enabling the minor mode if you enter C-x and wait for the default of 1 second the minibuffer will expand with all of the available key bindings that follow C-x (or as many as space allows given your settings). This includes prefixes like C-x 8 which are shown in a different face. Screenshots of what the popup will look like are included below. which-key started as a rewrite of [[https://github.com/kai2nenobu/guide-key][gude-key-mode]], but the feature sets have diverged to a certain extent. GitHub: https://github.com/justbur/emacs-which-key #+BEGIN_SRC emacs-lisp (use-package which-key :ensure t :commands (which-key-mode) :config (which-key-mode) ;; Reset to the default or customized value before adding our values in order ;; to make this initialization code idempotent. (custom-reevaluate-setting 'which-key-replacement-alist) ;; Use my own rules for better naming of functions (let ((desc ;; being higher in this list means the replacement is applied later '(("er/expand-region" . "expand region") ("evil-lisp-state-\\(.+\\)" . "\\1") ;; my own commands prefix with `my/' ("my/\\(.+\\)" . "\\1") ))) (dolist (nd desc) ;; ensure the target matches the whole string (push (cons (cons nil (concat "\\`" (car nd) "\\'")) (cons nil (cdr nd))) which-key-replacement-alist)))) #+END_SRC ** zzz-to-char :keybinding: This package provides two new commands: =zzz-to-char= and =zzz-up-to-char= which work like built-ins zap-to-char and zap-up-to-char, but allow you quickly select exact character you want to “zzz” to. The commands are minimalistic and often work like built-in ones when there is only one occurrence of target character (except they automatically work in backward direction too). You can also specify how many characters to scan from each side of point, see =zzz-to-char-reach=. This package uses avy as backend. GitHub: https://github.com/mrkkrp/zzz-to-char #+BEGIN_SRC emacs-lisp (use-package zzz-to-char :ensure t :bind (("M-z" . zzz-to-char))) #+END_SRC * Interactive Commands :command: In emacs, we can use =M-x= to execute interactive commands, I implement some of them to make my emacs more easy to use. All my =commands= starts with =my/= prefix. ** Buffers :buffer: *** Kill all buffers except *scratch* buffer Sometimes I just want to kill all buffers, this command will kill all of them and make =*scratch*= buffer alone. #+BEGIN_SRC emacs-lisp (defun my/nuke-all-buffers () "Kill all buffers, leaving *scratch* only." (interactive) (mapcar (lambda (x) (kill-buffer x)) (buffer-list)) (delete-other-windows)) #+END_SRC *** Make emacs can always save buffers (even if file is not modified) The default command *save-buffer* will not really save file when it untouched, use this command can let me force save file even if file is not modified. #+BEGIN_SRC emacs-lisp (defun my/save-buffer-always () "Save the buffer even if it is not modified." (interactive) (set-buffer-modified-p t) (save-buffer)) #+END_SRC *** Abort minibuffer recursive edit #+BEGIN_SRC emacs-lisp (defun my/minibuffer-keyboard-quit () "Abort recursive edit. In Delete Selection mode, if the mark is active, just deactivate it; then it takes a second \\[keyboard-quit] to abort the minibuffer." (interactive) (if (and delete-selection-mode transient-mark-mode mark-active) (setq deactivate-mark t) (when (get-buffer "*Completions*") (delete-windows-on "*Completions*")) (abort-recursive-edit))) #+END_SRC *** Make buffer untabify #+BEGIN_SRC emacs-lisp (defun my/untabify-buffer () (interactive) (save-excursion (untabify (point-min) (point-max)))) #+END_SRC *** Indent whole buffer #+BEGIN_SRC emacs-lisp (defun my/indent-whole-buffer () "Indent whole buffer." (interactive) (save-excursion (indent-region (point-min) (point-max)))) #+END_SRC *** Remove buffers trailing whitespace and untabify #+BEGIN_SRC emacs-lisp (defun my/cleanup-buffer () "Perform a bunch of operations on the whitespace content of a buffer." (interactive) (save-excursion (delete-trailing-whitespace) (indent-region (point-min) (point-max)) (untabify (point-min) (point-max)))) #+END_SRC *** Replace the preceding sexp with its value #+BEGIN_SRC emacs-lisp (defun my/eval-and-replace () "Replace the preceding sexp with its value." (interactive) (backward-kill-sexp) (condition-case nil (prin1 (eval (read (current-kill 0))) (current-buffer)) (error (message "Invalid expression") (insert (current-kill 0))))) #+END_SRC *** Quick folding source block #+BEGIN_SRC emacs-lisp (defun my/quick-folding-source () "Use emacs buildin easy to folding code." (interactive) (set-selective-display (if selective-display nil 1))) #+END_SRC *** Convert file format between DOS and UNIX Some of my partner's file are in DOS format, so I need command to convert buffer between dos format and unix format. #+begin_src emacs-lisp (defun my/dos2unix () "Convert buffer file from dos file to unix file." (interactive) (set-buffer-file-coding-system 'undecided-unix 't) ) #+end_src #+begin_src emacs-lisp (defun my/unix2dos () "Convert buffer file from unix file to dos file." (interactive) (set-buffer-file-coding-system 'undecided-dos 't)) #+end_src ** Edit (Insert/Remove) :edit: *** Insert U200B char = = character is a =zero width space character= which is nice to use under org-mode. For more info, please see: [[https://lists.gnu.org/archive/html/emacs-orgmode/2012-09/msg00155.html][suggestion for org-emphasis-regexp-components: *U*nited *N*ations]] #+BEGIN_SRC emacs-lisp (defun my/insert-U200B-char () "Insert char, this character is nice use in org-mode." (interactive) (insert "\ufeff")) #+END_SRC *** Insert empty line after current line #+BEGIN_SRC emacs-lisp (defun my/insert-empty-line () "Insert an empty line after current line and position cursor on newline." (interactive) (move-end-of-line nil) (open-line 1) (forward-line 1)) #+END_SRC *** Insert lorem ipsum #+BEGIN_SRC emacs-lisp (defun my/insert-lorem () "Insert a lorem ipsum." (interactive) (insert "Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do " "eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim" "ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut " "aliquip ex ea commodo consequat. Duis aute irure dolor in " "reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla " "pariatur. Excepteur sint occaecat cupidatat non proident, sunt in " "culpa qui officia deserunt mollit anim id est laborum.")) #+END_SRC *** Delete word #+BEGIN_SRC emacs-lisp (defun my/delete-word (arg) "Delete characters forward until encountering the end of a word. With argument, do this that many times." (interactive "p") (delete-region (point) (progn (forward-word arg) (point)))) #+END_SRC *** Set mark or expand region #+BEGIN_SRC emacs-lisp (defun my/set-mark-mode/rectangle-mark-mode () "toggle between set-mark-command or rectangle-mark-mode" (interactive) (if (not mark-active) (call-interactively 'set-mark-command) (call-interactively 'rectangle-mark-mode))) #+END_SRC *** Copy and comments #+BEGIN_SRC emacs-lisp (defun my/copy-and-comment () "Copy region and comment it." (interactive) (kill-ring-save (region-beginning) (region-end)) (comment-dwim nil)) #+END_SRC ** File Handle :file: *** Reopen file as root #+BEGIN_SRC emacs-lisp (defun my/file-reopen-as-root () (interactive) (when buffer-file-name (find-alternate-file (concat "/sudo:root@localhost:" buffer-file-name)))) #+END_SRC *** Delete current buffer file #+BEGIN_SRC emacs-lisp (defun my/delete-current-buffer-file () "Remove file connected to current buffer and kill buffer." (interactive) (let ((filename (buffer-file-name)) (buffer (current-buffer))) (if (not (and filename (file-exists-p filename))) (ido-kill-buffer) (when (yes-or-no-p "Are you sure you want to remove this file? ") (delete-file filename) (kill-buffer buffer) (message "File '%s' successfully removed" filename))))) #+END_SRC *** Rename current Buffer and file #+BEGIN_SRC emacs-lisp (defun my/rename-current-buffer-file () "Renames current buffer and file it is visiting." (interactive) (let ((name (buffer-name)) (filename (buffer-file-name))) (if (not (and filename (file-exists-p filename))) (error "Buffer '%s' is not visiting a file!" name) (let ((new-name (read-file-name "New name: " filename))) (if (get-buffer new-name) (error "A buffer named '%s' already exists!" new-name) (rename-file filename new-name 1) (rename-buffer new-name) (set-visited-file-name new-name) (set-buffer-modified-p nil) (message "File '%s' successfully renamed to '%s'" name (file-name-nondirectory new-name))))))) #+END_SRC *** Add executable attribute to file Actually this command is the same as =chmod +x= but it doesn't use any shell command, it use emacs's logior function to change file attribute. I only make =owener= can has executable permission, not change it for gourp or others user. #+BEGIN_SRC emacs-lisp (defun my/set-file-executable() "Add executable permissions on current file." (interactive) (when (buffer-file-name) (set-file-modes buffer-file-name (logior (file-modes buffer-file-name) #o100)) (message (concat "Made " buffer-file-name " executable")))) #+END_SRC *** Clone current file to new one #+BEGIN_SRC emacs-lisp (defun my/clone-file-and-open (filename) "Clone the current buffer writing it into FILENAME and open it" (interactive "FClone to file: ") (save-restriction (widen) (write-region (point-min) (point-max) filename nil nil nil 'confirm)) (find-file filename)) #+END_SRC *** Show current buffer-file information #+BEGIN_SRC emacs-lisp (defun my/file-info () "Show current buffer information." (interactive) (if (buffer-file-name (current-buffer)) (progn (let* ((file-name (buffer-file-name (current-buffer))) (f-attr (file-attributes file-name)) (f-size (nth 7 f-attr)) ; ファイルサイズ (f-mode (nth 8 f-attr)) ; ファイル属性 (mes1 (format "file path: %s\n" file-name)) (mes2 (format "file size: %s byte\n" f-size)) (mes3 (format "file type: %s" f-mode)) (mess (concat mes1 mes2 mes3))) (message "%s" mess))) nil)) #+END_SRC ** Debug :debug: *** Eval emacs buffer until error A really nice command help me to find error on elisp buffer. #+BEGIN_SRC emacs-lisp (defun my/eval-buffer-until-error () "Evaluate emacs buffer until error occured." (interactive) (goto-char (point-min)) (while t (eval (read (current-buffer))))) #+END_SRC *** Display face found at the current point #+BEGIN_SRC emacs-lisp (defun my/what-face (pos) "Display face found at the current point." (interactive "d") (let ((face (or (get-char-property (point) 'read-face-name) (get-char-property (point) 'face)))) (if face (message "Face: %s" face) (message "No face at %d" pos)))) #+END_SRC *** Reload emacs init config #+BEGIN_SRC emacs-lisp (defun my/reload-init () "Reload init.el file" (interactive) (load-file user-init-file)) #+END_SRC ** Window :window: *** Switch to other window or split it If other window does not exist, split it, else switch to it. #+BEGIN_SRC emacs-lisp (defun my/other-window-or-split () "Switch to other window or split it." (interactive) (when (one-window-p) (split-window-horizontally)) (other-window 1)) #+END_SRC *** Swap left/right windows If I have two windows at left/right position, this command can help me change left-window to right-window. #+BEGIN_SRC emacs-lisp (defun my/swap-window-positions () "*Swap the positions of this window and the next one." (interactive) (let ((other-window (next-window (selected-window) 'no-minibuf))) (let ((other-window-buffer (window-buffer other-window)) (other-window-hscroll (window-hscroll other-window)) (other-window-point (window-point other-window)) (other-window-start (window-start other-window))) (set-window-buffer other-window (current-buffer)) (set-window-hscroll other-window (window-hscroll (selected-window))) (set-window-point other-window (point)) (set-window-start other-window (window-start (selected-window))) (set-window-buffer (selected-window) other-window-buffer) (set-window-hscroll (selected-window) other-window-hscroll) (set-window-point (selected-window) other-window-point) (set-window-start (selected-window) other-window-start)) (select-window other-window))) #+END_SRC * Styles :style: My own emacs, my own style :) ** General Setups Some emacs's default UI feature setup. *** Turn-off menu bar The menu bar is one of the UI elements which work best with mouses. #+BEGIN_SRC emacs-lisp (when (featurep 'menu-bar) (menu-bar-mode -1)) #+END_SRC *** Turn-off tool bar I never use the tool bar, it's really no need. #+BEGIN_SRC emacs-lisp (when (featurep 'tool-bar) (tool-bar-mode -1)) #+END_SRC *** Turn-off blinking cursor I hate the blinking cursor actually, it's really annoying. #+BEGIN_SRC emacs-lisp (blink-cursor-mode -1) #+END_SRC *** Turn-off scroll bar Actually when you familier with emacs, you don't need to use scroll-bar anymore. #+BEGIN_SRC emacs-lisp (when (featurep 'scroll-bar) (scroll-bar-mode -1)) #+END_SRC *** Turn-off startup screen I don't want to enter the startup screen after initialize emacs. #+BEGIN_SRC emacs-lisp (setq inhibit-startup-screen t) #+END_SRC ** Theme Before use emacs's =load-theme= function, I advise it to make it fully unload previous theme before loading a new one. #+BEGIN_SRC emacs-lisp ;; Make `load-theme' fully unload previous theme before loading a new one. (defadvice load-theme (before theme-dont-propagate activate) (mapc #'disable-theme custom-enabled-themes)) #+END_SRC I always want to customize everything on my own, so I build my own emacs theme called =night-coldnew= and =day-coldnew=, you can find them at styles dir. - [[file:styles/coldnew-theme.el]] Basic utils and macros to define coldnew-theme. - [[file:styles/day-coldnew-theme.el]] My day theme. - [[file:styles/night-coldnew-theme.el]] My night theme. #+BEGIN_SRC emacs-lisp (require 'day-coldnew-theme) (require 'night-coldnew-theme) (load-theme 'night-coldnew t nil) ; default use `night-coldnew-theme' #+END_SRC ** mode-line #+BEGIN_SRC emacs-lisp (require 'coldnew-modeline-config) ;; (use-package spaceline :ensure t) ;; (use-package spaceline-all-the-icons ;; :after spaceline ;; :config ;; (spaceline-all-the-icons-theme) ;; ;; ;; (setq spaceline-all-the-icons-separators-type 'slant)) #+END_SRC #+BEGIN_SRC emacs-lisp :tangle no ;; (use-package spaceline :ensure t) ;; (use-package spaceline-all-the-icons ;; :after spaceline ;; :config ;; (spaceline-all-the-icons-theme) ;; ;; ;; (setq spaceline-all-the-icons-separators-type 'slant)) (require 'org-timer) (defface mode-line-read-only-face '((t (:foreground "#C82829" :bold t))) "face for mode-name-string in modeline." :group 'mode-line) (defface mode-line-modified-face '((t (:inherit 'font-lock-function-name-face :bolt t))) "face for mode-name-string in modeline." :group'mode-lin) (defface mode-line-mode-name-face '((t (:inherit font-lock-keyword-face))) "face for mode-name-string in modeline." :group 'mode-line) (defface font-lock-escape-char-face '((((class color)) (:foreground "seagreen2"))) "highlight c escapes char like vim" :group 'font-lock-faces) (defun my/org-timer-modeline () "Show `org-timer' info in my custom mode-line." (if (or org-timer-mode-line-timer org-timer-countdown-timer (org-at-item-timer-p) ) ;; - `org-timer-value-string' ;; - `org-timer-set-mode-line' ;; - `org-timer-mode-line-string' (propertize (concat ;; (all-the-icons-material "alarm_on" :v-adjust 0.05) (format "%s" org-timer-mode-line-string)) 'face 'font-lock-function-name-face) "")) (defun my/org-clock-modeline () "Show org-clock info." (when org-clock-idle-timer ;; get [0:05] from `org-clock-get-clock-string' (propertize (concat ;; (all-the-icons-octicon "clock" :v-adjust 0.05) "clock: " (propertize " " 'face 'variable-pitch) (format "%s" (org-minutes-to-clocksum-string (org-clock-get-clocked-time)))) 'face 'font-lick-exit-face)) ;; org-clock-today (show current org clock) ;; NOTE: this time is doubled on `org-clock'. ;; (:eval ;; (when (and (org-clock-is-active) (active)) ;; (list ;; (propertize (format" ⏰%s"org-clock-today-string) ;; 'face'(:foreground"cyan"))) ;; )) ) ;; update org-clock timer in mode-line after `org-clock-out-hook'. ;; fix org-clock timer does not disappear after clock out. (add-hook 'org-clock-out-hook '(lambda () ;; (org-clock-update-mode-line) (setq org-mode-line-string nil) (force-mode-line-update))) (defun mode-line-buffer-permissions () "Get buffer-file permissions." (when (buffer-file-name) (format "-%04o-" (file-modes (buffer-file-name))))) (defun mode-line-major-mode () "Get major-mode name with << >>." (concat "<< " (propertize mode-name 'face 'mode-line-mode-name-face) " >>")) (setq-default mode-line-format '((" " mode-line-mule-info ;; read-only or modified status (:eval (cond (buffer-read-only (propertize "RO" 'face 'mode-line-read-only-face)) ((buffer-modified-p) (propertize "**" 'face 'mode-line-modified-face)) (t "--"))) " " ;; (when (featurep 'evil) ;; (:eval (evil-mode-string))) " " mode-line-buffer-identification " " ;; (:eval (mode-line-buffer-permissions)) " " ;; major-mode name (:eval (mode-line-major-mode)) " " (:eval (my/org-timer-modeline)) " " (:eval (my/org-clock-modeline)) " " ;; line and column "(" (:eval (propertize "%02l" 'face 'font-lock-type-face)) "," (:eval (propertize "%02c" 'face 'font-lock-type-face)) ")" " " (vc-mode vc-mode) " " ;; (org-timer-mode-line-timer ;; (:eval (format " <%s> " ;; (let ((time (abs (floor (org-timer-seconds))))) ;; (cond ;; ((< time 30) "#ef2929") ;; ((< time 60) "#f57900") ;; (t "#8cc4ff"))) ;; (substring (org-timer-value-string) 0 -1)))) " " ;; relative position, size of file "[" (:eval (propertize "%p" 'face 'font-lock-constant-face)) ;; % above top "/" (:eval (propertize "%I" 'face 'font-lock-constant-face)) ;; size "] " ))) (force-mode-line-update) #+END_SRC * TODO Fonts #+BEGIN_SRC emacs-lisp (defvar my/emacs-english-font "Monaco" "The font name of English.") (defvar my/emacs-cjk-font "Hiragino Sans GB" "The font name for CJK.") (defvar my/emacs-font-size-pair '(13 . 16) "Default font size pair for (english . chinese)") (defun my/font-exist-p (fontname) "Test if this font is exist or not. This function only work on GUI mode, on terminal it just return nil since you can't set font for emacs on it." (if (or (not fontname) (string= fontname "") (not (display-graphic-p))) nil (if (not (x-list-fonts fontname)) nil t))) (defun my/set-font (english chinese size-pair) "Setup emacs English and Chinese font on x window-system." (if (my/font-exist-p english) (set-frame-font (format "%s:pixelsize=%d" english (car size-pair)) t)) (if (my/font-exist-p chinese) (dolist (charset '(kana han cjk-misc bopomofo)) (set-fontset-font (frame-parameter nil 'font) charset (font-spec :family chinese :size (cdr size-pair)))))) ;; Setup font size based on my/emacs-font-size-pair (my/set-font my/emacs-english-font my/emacs-cjk-font my/emacs-font-size-pair) (defvar my/emacs-font-size-pair-list '(( 5 . 6) (10 . 12) (13 . 16) (15 . 18) (17 . 20) (19 . 22) (20 . 24) (21 . 26) (24 . 28) (26 . 32) (28 . 34) (30 . 36) (34 . 40) (36 . 44)) "This list is used to store matching (english . chinese) font-size.") (defun my/emacs-step-font-size (step) "Increase/Decrease emacs's font size." (let ((scale-steps my/emacs-font-size-pair-list)) (if (< step 0) (setq scale-steps (reverse scale-steps))) (setq my/emacs-font-size-pair (or (cadr (member my/emacs-font-size-pair scale-steps)) my/emacs-font-size-pair)) (when my/emacs-font-size-pair (message "emacs font size set to %.1f" (car my/emacs-font-size-pair)) (my/set-font my/emacs-english-font my/emacs-cjk-font my/emacs-font-size-pair)))) (defun my/increase-emacs-font-size () "Decrease emacs's font-size acording emacs-font-size-pair-list." (interactive) (my/emacs-step-font-size 1)) (defun my/decrease-emacs-font-size () "Increase emacs's font-size acording emacs-font-size-pair-list." (interactive) (my/emacs-step-font-size -1)) #+END_SRC ** Setup Keybinds :keybinding: #+BEGIN_SRC emacs-lisp (bind-keys :map global-map ("C-=" . my/increase-emacs-font-size) ("C--" . my/decrease-emacs-font-size)) #+END_SRC * Minibuffer :minibuffer: #+BEGIN_SRC emacs-lisp :noweb no-export :exports code (when (require 'minibuffer) ; buildin <>) #+END_SRC ** Make cursor in minibufer use bar shape #+BEGIN_SRC emacs-lisp :tangle no :noweb-ref minibuffer-config ;; only use `bar' type of cursor shape (add-hook 'minibuffer-setup-hook '(lambda () (setq cursor-type 'bar))) #+END_SRC ** Some helper function to let me insert quick in minibuffer #+BEGIN_SRC emacs-lisp :tangle no :noweb-ref minibuffer-config ;; define some helper function to insert to minibuffer quickly (defun my/minibuffer-insert (p) (kill-line 0) (insert p)) (defun my/minibuffer-switch-to-ramdisk () "Insert ramdisk path according to system type" (interactive) (my/minibuffer-insert user-ramdisk-directory)) (defun my/minibuffer-switch-to-home () "Insert $HOME path." (interactive) (my/minibuffer-insert (file-name-as-directory (getenv "HOME")))) (defun my/minibuffer-switch-to-rootdir () "Insert / path." (interactive) (my/minibuffer-insert "/")) (defun my/minibuffer-switch-to-tramp () "Insert /ssh:." (interactive) (my/minibuffer-insert "/ssh:")) #+END_SRC ** Save history of minibuffer :tangle no :noweb-ref minibuffer-config When Savehist mode is enabled, minibuffer history is saved periodically and when exiting Emacs. When Savehist mode is enabled for the first time in an Emacs session, it loads the previous minibuffer history from ‘savehist-file’. #+BEGIN_SRC emacs-lisp :tangle no :noweb-ref minibuffer-config (use-package savehist :config (setq savehist-file (concat user-cache-directory "savehist.dat")) (savehist-mode 1)) #+END_SRC ** Setup Keybindings :keybinding: #+BEGIN_SRC emacs-lisp :tangle no :noweb-ref minibuffer-config (bind-keys :map minibuffer-local-map ("C-w" . backward-kill-word) ("M-p" . previous-history-element) ("M-n" . next-history-element) ("C-g" . minibuffer-keyboard-quit) ("M-t" . my/minibuffer-switch-to-ramdisk) ("M-h" . my/minibuffer-switch-to-home) ("M-/" . my/minibuffer-switch-to-rootdir) ("M-s" . my/minibuffer-switch-to-tramp)) #+END_SRC * Vim Emulation :evil: Though I am really familier with emacs, I still like some vim command. #+BEGIN_SRC emacs-lisp :noweb no-export :exports code (use-package evil :ensure t :config ;; enable evil-mode globally (evil-mode t) ;; some configs setup later < > ;; extra keybindings defined in `Keybinding' section < > < >) #+END_SRC ** Setup default state to insert-state #+BEGIN_SRC emacs-lisp :tangle no :noweb-ref evil-config ;; default state set to insert-state (setq evil-default-state 'insert) #+END_SRC ** Make insert-state the same as emacs-state To me, vim's insert state is useless, so I mapping all my emacs keybinding to insert-state. First, bind all emacs-state key to insert state #+BEGIN_SRC emacs-lisp :tangle no :noweb-ref evil-config (setcdr evil-insert-state-map nil) (define-key evil-insert-state-map (read-kbd-macro evil-toggle-key) 'evil-emacs-state) #+END_SRC Make sure =ESC= key in insert-state will call =evil-normal-state=. #+BEGIN_SRC emacs-lisp :tangle no :noweb-ref evil-config (define-key evil-insert-state-map [escape] 'evil-normal-state) #+END_SRC We also need to make all emacs-state buffer become to insert-state. #+BEGIN_SRC emacs-lisp :tangle no :noweb-ref evil-config (dolist (m evil-emacs-state-modes) (add-to-list 'evil-insert-state-modes m)) #+END_SRC ** evil-leader Evil Leader provides the = = feature from Vim that provides an easy way to bind keys under a variable prefix key. For an experienced Emacs User it is nothing more than a convoluted key map, but for a Evil user coming from Vim it means an easier start. GitHub: https://github.com/cofi/evil-leader #+BEGIN_SRC emacs-lisp :noweb no-export :exports code (use-package evil-leader :ensure t :after evil :config ;; enable evil-leader globally (global-evil-leader-mode) ;; extra keybindings defined in `Keybinding' section < > ) #+END_SRC ** evil-surround This package emulates [[https://github.com/tpope/vim-surround][surround.vim by Tim Pope]]. The functionality is wrapped into a minor mode. GitHub: https://github.com/timcharper/evil-surround #+BEGIN_SRC emacs-lisp (use-package evil-surround :ensure t :after evil :config (global-evil-surround-mode 1)) #+END_SRC ** evil-quickscope This package emulates [[https://github.com/unblevable/quick-scope][quick_scope.vim by Brian Le]]. It highlights targets for evil-mode’s f,F,t,T keys, allowing for quick navigation within a line with no additional mappings. GitHub: https://github.com/blorbx/evil-quickscope #+BEGIN_SRC emacs-lisp (use-package evil-quickscope :ensure t :after evil :config (add-hook 'prog-mode-hook 'turn-on-evil-quickscope-always-mode)) #+END_SRC ** Displays tildes in the fringe on empty lines a la Vi GitHub: https://github.com/syohex/vi-tilde-fringe #+BEGIN_SRC emacs-lisp (use-package vi-tilde-fringe :ensure t :if window-system :config (global-vi-tilde-fringe-mode)) #+END_SRC ** Make terminal support evil's cursor shape change This package changing cursor shape and color by evil state for evil-mode. Supported terminal: xterm, gnome-terminal, iTerm, konsole. GitHub: https://github.com/7696122/evil-terminal-cursor-changer #+BEGIN_SRC emacs-lisp (use-package evil-terminal-cursor-changer :ensure t :if (not (display-graphic-p)) ; Only use this package when in terminal :config ;; cursor shape setting (setq evil-motion-state-cursor 'box) ; █ (setq evil-visual-state-cursor 'box) ; █ (setq evil-normal-state-cursor 'box) ; █ (setq evil-insert-state-cursor 'bar) ; ⎸ (setq evil-emacs-state-cursor 'hbar) ; _ ;; enable this package (evil-terminal-cursor-changer-activate)) #+END_SRC * Editor :editor: Why emacs config has an editor section, doesn't means emacs is not an editor ? Yes, Emacs is an OS :) I put some editor/IDE relative functions and packages here. ** Create minor-mode to controll all keybindings :keybinding: #+begin_src emacs-lisp (defvar my-editor-map (make-keymap)) (define-minor-mode my-editor-mode "My editor minor mode." :init-value t :keymap my-editor-map) (define-globalized-minor-mode global-my-editor-mode my-editor-mode (lambda () (if (not (minibufferp (current-buffer))) (my-editor-mode 1)))) ;; Gloabal enable (global-my-editor-mode t) #+end_src ** Keeping files in sync By default, Emacs will not update the contents of open buffers when a file changes on disk. This is inconvenient when switching branches in Git - as you’d risk editing stale buffers. This problem can be solved by: #+BEGIN_SRC emacs-lisp (global-auto-revert-mode 1) (setq global-auto-revert-non-file-buffers
本源码包内暂不包含可直接显示的源代码文件,请下载源码包。