Ecosyste.ms: Awesome

An open API service indexing awesome lists of open source software.

https://github.com/coldnew/coldnew-emacs

coldnew's emacs config
https://github.com/coldnew/coldnew-emacs

configuration emacs emacs-lisp org-mode

Last synced: 3 months ago
JSON representation

coldnew's emacs config

Lists

README

        

#+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]] with [[https://github.com/daviderestivo/homebrew-emacs-head][homebrew-emacs-head]], I always install latest version of emacs via following command:

#+BEGIN_SRC sh :tangle no
brew tap daviderestivo/emacs-head
brew install emacs-head@30 --with-cocoa --with-gnutls --with-ctags --with-mailutils --with-xwidgets --with-native-comp --with-native-full-aot --with-tree-sitter
ln -s /opt/homebrew/opt/emacs-head@30/Emacs.app /Applications
#+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$\\)"))
;; This variable is obsolete since 29.1
(setq-default native-comp-deferred-compilation-deny-list '("\\(?:[^z-a]*-autoloads\\.el$\\)"))
;; introduce in emacs 28.1
(setq-default native-comp-jit-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)))
;; my-lisp-dir should always exist, but sys-lisp-dir may not exist
(dolist (lisp-path my-lisp-dir)
(when (not (file-exists-p lisp-path))
(make-directory lisp-path t)))
(dolist (lisp-path lisp-dir)
(when (file-exists-p lisp-path)
(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 "[email protected]")
#+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

NOTE:

=use-package= is integrated in emacs directly since emacs 29.1, it's no need to install it manually anymore.

#+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

** 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
(defvar bootstrap-version)
(let ((bootstrap-file
(expand-file-name "straight/repos/straight.el/bootstrap.el" user-emacs-directory))
(bootstrap-version 6))
(unless (file-exists-p bootstrap-file)
(with-current-buffer
(url-retrieve-synchronously
"https://raw.githubusercontent.com/radian-software/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.

** 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
:config
(when (memq window-system '(mac ns x))
(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

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

* 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

** evil-terminal-cursor-changer

evil-terminal-cursor-changer is changing cursor shape and color by evil state for evil-mode.

When running in terminal, It's especially helpful to recognize evil's state.

GitHub: https://github.com/7696122/evil-terminal-cursor-changer

#+BEGIN_SRC emacs-lisp
(use-package evil-terminal-cursor-changer
:ensure t
:after evil
:commands (evil-terminal-cursor-changer-activate)
:config (evil-terminal-cursor-changer-activate))
#+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 t)
(setq auto-revert-verbose nil)
(setq revert-without-query '(".*")) ;; disable revert query
#+END_SRC

** Disable lock file

I don't want emacs create some temporary file like =.#-emacs-a08196=, disable it.

#+BEGIN_SRC emacs-lisp
;; https://www.emacswiki.org/emacs/LockFiles
(when (version<= "24.3" emacs-version)
(setq create-lockfiles nil))
#+END_SRC

** Add support for editorconfig :editorconfig:

[[http://editorconfig.org/][EditorConfig]] helps developers define and maintain consistent coding styles between different editors and IDEs. The EditorConfig project consists of a file format for defining coding styles and a collection of text editor plugins that enable editors to read the file format and adhere to defined styles. EditorConfig files are easily readable and they work nicely with version control systems.

see: http://editorconfig.org/

GitHub: https://github.com/editorconfig/editorconfig-emacs

#+BEGIN_SRC emacs-lisp
(use-package editorconfig
:ensure t
:if (executable-find "editorconfig")
:mode ("\\.editorconfig\\'" . conf-unix-mode)
:commands editorconfig-mode
:init
(add-hook 'prog-mode-hook #'editorconfig-mode))
#+END_SRC

*** Install System Packages

To use [[https://editorconfig.org][editorconfig]] 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 editorconfig
#+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-text/editorconfig-core-c
#+END_SRC

** En/Decrypt files by EasyPG

#+BEGIN_SRC emacs-lisp
(require 'epa-file) ; part of emacs
;; Enable epa, so I can use gnupg in emacs to en/decrypt file
(epa-file-enable)
;; Control whether or not to pop up the key selection dialog.
(setq epa-file-select-keys 0)
;; Cache passphrase for symmetric encryption.
(setq epa-file-cache-passphrase-for-symmetric-encryption t)
#+END_SRC

*** Install gnupg to system

For Mac OSX, just type

#+BEGIN_SRC sh :tangle no :noweb-ref install-in-macosx
brew install gpg
#+END_SRC

Most Linux already shipped with gnupg, if you use Gentoo Linux, you can use following command to install it

#+BEGIN_SRC sh :tangle no :noweb-ref install-in-gentoo
emerge app-crypt/gnupg
#+END_SRC

In my system, I always use =gpg2= instead of =gpg1=.

*** Make pinentry show on mini-buffer

For me, when enter password on gpg encrypt file, I always want the password input prompt show on minibuffer, so I need to add more setup on the gnupg.

First, put this in =~/.gnupg/gpg-agent.conf=

#+BEGIN_SRC sh :tangle no
allow-emacs-pinentry
allow-loopback-pinentry

# (optional) setup timeout
pinentry-timeout 3
#+END_SRC

Then tell gpg-agent to load this configuration with =gpgconf= in a shell:

: gpgconf --reload gpg-agent

In your emacs, put this epa setup:

#+BEGIN_SRC emacs-lisp
(require 'epa) ; built-in
(setq epg-pinentry-mode 'loopback)
#+END_SRC

All things done, let's start the =pinentry server=:

#+BEGIN_SRC emacs-lisp
(use-package pinentry
:ensure t
:config
;; Start the Pinentry service
(pinentry-start))
#+END_SRC

** Remote file editing

#+BEGIN_SRC emacs-lisp
(use-package tramp
:ensure t
:init
(setq tramp-persistency-file-name (concat user-cache-directory "tramp"))
:config
(setq tramp-default-method "rsync"))
#+END_SRC

** Line Numbers

In most case, I'll make line numers display globally by =linum=.

#+BEGIN_SRC emacs-lisp
(if (version<= "26.1" emacs-version)
;; emacs 26.1 has display-line-number-mode, which is written in C
(progn
(require 'display-line-numbers)
;; Only use line number in `prog-mode-hook'
(add-hook 'prog-mode-hook #'display-line-numbers-mode))
;; for emacs version less than 26, use linum instead
(use-package linum :ensure t :init (global-linum-mode 1)))
#+END_SRC

Disable line number in some mode, for example, since =org-mode= can
has many lines, it's not recommand to enable linum-mode.

I use =linum-off= to disable some mode.

#+BEGIN_SRC emacs-lisp
;; disble some mode with linum
(use-package linum-off
:ensure t
:config
(setq linum-disabled-mode-list
'(eshell-mode shell-mode term-mode erc-mode compilation-mode
woman-mode w3m-mode calendar-mode org-mode)))

;; for emacs 26.1 or above, we use `display-line-number-mode' instead
(when (version<= "26.1" emacs-version)
;; NOTE: overwrite display-line-numbers--turn-on
(defun display-line-numbers--turn-on ()
"Turn on `display-line-numbers-mode'."
(unless (or (minibufferp)
;; taken from linum.el
(and (daemonp) (null (frame-parameter nil 'client)))
;; take code from `linum-off'
(member major-mode linum-disabled-modes-list))
(display-line-numbers-mode))))
#+END_SRC

** Colorfy delimters

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

#+BEGIN_SRC emacs-lisp
(use-package rainbow-delimiters
:ensure t
:config
(add-hook 'prog-mode-hook 'rainbow-delimiters-mode))
#+END_SRC

** Save recent file info :recentf:

#+BEGIN_SRC emacs-lisp
(use-package recentf
:straight (:type built-in)
:init (setq recentf-save-file (expand-file-name "recentf" user-cache-directory))
:config
(recentf-mode 1))
#+END_SRC

** Highlight numbers

=highlight-numbers= is an Emacs minor mode that highlights numeric literals in
source code.

GitHub: https://github.com/Fanael/highlight-numbers

#+BEGIN_SRC emacs-lisp
(use-package highlight-numbers
:ensure t
:config
;; json-mode has it's own highlight numbers method
(add-hook 'prog-mode-hook #'(lambda()
(if (not (derived-mode-p 'json-mode))
(highlight-numbers-mode)))))
#+END_SRC

** Highlight escape charset

GitHub: https://github.com/dgutov/highlight-escape-sequences

#+BEGIN_SRC emacs-lisp
(use-package highlight-escape-sequences
:ensure t
:config
;; Make face the same as builtin face
(put 'font-lock-regexp-grouping-backslash 'face-alias 'font-lock-builtin-face)
;; Enable globally
(hes-mode 1))
#+END_SRC

** Highlight FIXME, TODO

#+begin_src emacs-lisp
(defun font-lock-comment-annotations ()
"Highlight a bunch of well known comment annotations.
This functions should be added to the hooks of major modes for programming."
(font-lock-add-keywords
nil
'(("\\<\\(FIX\\(ME\\)?\\|BUG\\|HACK\\):" 1 font-lock-warning-face t)
("\\<\\(NOTE\\):" 1 'org-level-2 t)
("\\<\\(TODO\\):" 1 'org-todo t)
("\\<\\(DONE\\):" 1 'org-done t))
))

(add-hook 'prog-mode-hook 'font-lock-comment-annotations)
#+end_src

** Show vertical lines to guide indentation

GitHub: https://github.com/zk-phi/indent-guide

#+BEGIN_SRC emacs-lisp
(use-package indent-guide
:ensure t
:config
;; Only show indent-guide in idle-time.
(setq indent-guide-delay 0.1))
#+END_SRC

** Visualization of matching parens

#+BEGIN_SRC emacs-lisp
(show-paren-mode 1)
(setq show-paren-delay 0) ; no delay
#+END_SRC

** Adapt to foreign indentation offsets

An Emacs minor mode that guesses the indentation offset originally
used for creating source code files and transparently adjusts the
corresponding settings in Emacs, making it more convenient to edit
foreign files.

GitHub: https://github.com/jscheid/dtrt-indent

#+BEGIN_SRC emacs-lisp
(use-package dtrt-indent
:ensure t
:config
;; enable dtrt-indent-mode globally
(dtrt-indent-mode 1))
#+END_SRC

** Intelligently call whitespace-cleanup on save

This Emacs library minor mode will intelligently call =whitespace-cleanup= before
buffers are saved.

=whitespace-cleanup= is a handy function, but putting it in =before-save-hook=
for every buffer is overkill, and causes messy diffs when editing third-party
code that did not initially have clean whitespace.

Additionally, whitespace preferences are often project-specific, and it's
inconvenient to set up =before-save-hook= in a =.dir-locals.el= file.

=whitespace-cleanup-mode= is a minor mode which calls =whitespace-cleanup=
before saving the current buffer, but only if the whitespace in the buffer was
initially clean. It determines this by quickly checking to see if
=whitespace-cleanup= would have any effect on the buffer.

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

#+BEGIN_SRC emacs-lisp
(use-package whitespace-cleanup-mode
:ensure t
:config
(add-hook 'prog-mode-hook 'whitespace-cleanup-mode))
#+END_SRC

** Make Firefox can call Emacs to edit textarea

Want to edit Firefox's textarea in emacs ?

First, you need to install [[https://addons.mozilla.org/zh-TW/firefox/addon/edit-with-emacs1][Edit with Emacs]] on Firefox.

Then, in emacs, add following code to install

#+BEGIN_SRC emacs-lisp
(use-package edit-server
:ensure t
:config
(edit-server-start))
#+END_SRC

** Setup TABS

#+BEGIN_SRC emacs-lisp
(setq tab-always-indent 'complete)
#+END_SRC

** Highlight symbols with overlay

#+BEGIN_SRC emacs-lisp
(use-package symbol-overlay
:ensure t
:config
(add-hook 'prog-mode-hook #'symbol-overlay-mode)
;; (global-set-key (kbd "M-i") 'symbol-overlay-put)
(define-key symbol-overlay-map (kbd "p") 'symbol-overlay-jump-prev) ;; 次のシンボルへ
(define-key symbol-overlay-map (kbd "n") 'symbol-overlay-jump-next) ;; 前のシンボルへ
(define-key symbol-overlay-map (kbd "C-g") 'symbol-overlay-remove-all) ;; ハイライトキャンセル
)
#+END_SRC

** TODO Scrolling

ref:
https://www.reddit.com/r/emacs/comments/8sw3r0/finally_scrolling_over_large_images_with_pixel/

#+BEGIN_SRC emacs-lisp
(setq mouse-wheel-scroll-amount '(1)) ; Distance in pixel-resolution to scroll each mouse wheel event.
(setq mouse-wheel-progressive-speed nil) ; Progressive speed is too fast for me.
#+END_SRC

** Undo with undo-tree :undo:

Standard Emacs undo is kind of confusing. [[http://www.dr-qubit.org/emacs.php#undo-tree][undo-tree]] replaces this with a simpler tree structure. It also allows us to visualize the tree directly.

GitHub: https://github.com/emacsmirror/undo-tree

#+BEGIN_SRC emacs-lisp
(use-package undo-tree
:ensure t
:commands (global-undo-tree-mode)
:config
;; Persistent undo-tree history across emacs sessions
(let ((dir
(file-name-as-directory (concat user-cache-directory "undo-tree"))))
(setq undo-tree-history-directory-alist `(("." . ,dir))))
;; Make undo-tree save history
(setq undo-tree-auto-save-history t)
;; global enable undo-tree
(global-undo-tree-mode))
#+END_SRC

* Buffer :buffer:
** Create *scratch* automatically

Sometimes I'll clean the =*scratch*= buffer by kill it, add following function
to let emacs re-create it automatically.

#+BEGIN_SRC emacs-lisp
;; Create *scratch* automatically
(run-with-idle-timer 1 t
#'(lambda ()
(unless (get-buffer "*scratch*")
(with-current-buffer (get-buffer-create "*scratch*")
(lisp-interaction-mode)))))
#+END_SRC

** Make buffer names unique

The library uniquify overrides Emacs' default mechanism for making buffer names unique (using suffixes like <2>, <3> etc.) with a more sensible behaviour which use parts of the file names to make the buffer names distinguishable.

For instance, buffers visiting =/tmp/Makefile= and =/projects/coldnew/Makefile= would be named =Makefile|tmp= and =Makefile|coldnew=, respectively (instead of =Makefile= and =Makefile<2>=).

#+BEGIN_SRC emacs-lisp
(use-package uniquify
:ensure nil ; built-in
:config
;; starting separator for buffer name components
(setq uniquify-separator " • ")
;; rerationalize buffer names after a buffer has been killed.
(setq uniquify-after-kill-buffer-p t)
;; ignore non file buffers
(setq uniquify-ignore-buffers-re "^\\*"))
#+END_SRC
* Bookmarks

** Set up default registers

In emacs, there's a =jump-to-register (C-x r j)= command which can quickly switch to the file you setup.

For more info, you can refer to: [[https://www.emacswiki.org/emacs/Registers][EmacsWiki: Registers]]

#+BEGIN_SRC emacs-lisp
(dolist
(r `(
;; emacs's config.org
(?e (file . "~/.emacs.d/init.org"))
;; tasks: todo
(?t (file . "~/Org/tasks/todo.org"))
;; tasks: personal
(?p (file . "~/Org/tasks/personal.org"))
;; tasks: work
(?w (file . "~/Org/tasks/work.org"))
;; Offilce docs
(?W (file . "~/Org/Weintek/index.org"))
;; My personal note
(?n (file . "~/Org/Note.org"))
;; blogging ideas
(?b (file . "~/Org/blog.org"))
;; Finance
(?f (file . "~/Org/finance/personal.org"))
))
(set-register (car r) (cadr r)))
#+END_SRC

** Setup Keybinding :keybinding:

#+BEGIN_SRC emacs-lisp
(bind-keys :map my-editor-map
;("C-x n" . bm-next)
;("C-x p" . bm-previous)
;("C-x ." . bm-toggle)
)
#+END_SRC
* Helm :helm:

#+BEGIN_SRC emacs-lisp :noweb no-export :exports code
(use-package helm
:straight t
:init
<>
:config
<>)
#+END_SRC

** Install System packages

Since [[https://github.com/emacs-helm/helm][helm]] integrate some external tool like [[https://www.gnu.org/software/global/][gtags]], [[http://cscope.sourceforge.net/][cscope]] ...etc. We need to install these tools to our 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 global
brew install cscope
#+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 dev-util/cscope
emerge dev-util/global
#+END_SRC

** Basic setup

Enable helm mode by default.

#+BEGIN_SRC emacs-lisp :tangle no :noweb-ref helm-init
(add-hook 'after-init-hook #'helm-mode)
(add-hook 'after-init-hook #'helm-autoresize-mode)
(add-hook 'after-init-hook #'helm-adaptive-mode)
(add-hook 'after-init-hook #'helm-popup-tip-mode)
#+END_SRC

** Use fuzzy match in helm

#+BEGIN_SRC emacs-lisp :tangle no :noweb-ref helm-config
;; Use fuzzy match in helm
(setq helm-M-x-fuzzy-match t)
(setq helm-buffers-fuzzy-matching t)
(setq helm-recentf-fuzzy-match t)
#+END_SRC

** Make helm can select anything even not match

#+BEGIN_SRC emacs-lisp :tangle no :noweb-ref helm-config
;; make helm can select anything even not match
(setq helm-move-to-line-cycle-in-source nil)
(setq helm-ff-search-library-in-sexp t)
(setq helm-ff-file-name-history-use-recentf t)
#+END_SRC

** helm-bm

GitHub: https://github.com/yasuyk/helm-bm

#+BEGIN_SRC emacs-lisp
(use-package helm-bm :ensure t :after (helm))
#+END_SRC

** helm-dash

This package uses [[http://www.kapeli.com/dash][Dash]] docsets inside emacs to browse documentation. Here's an article explaining the basic usage of it.

It doesn't require Dash app.

GitHub: https://github.com/areina/helm-dash

#+BEGIN_SRC emacs-lisp
(use-package helm-dash :ensure t :after (helm))
#+END_SRC

** helm-gtags

=helm-gtags.el= is GNU GLOBAL helm interface.

GitHub: https://github.com/syohex/emacs-helm-gtags

#+BEGIN_SRC emacs-lisp
(use-package helm-gtags
:ensure t
:after (helm)
:config
(setq helm-gtags-ignore-case t)
(setq helm-gtags-auto-update t)
(setq helm-gtags-use-input-at-cursor t)
(setq helm-gtags-pulse-at-cursor t)
;; add to following modes
(add-hook 'c-mode-hook #'helm-gtags-mode)
(add-hook 'c++-mode-hook #'helm-gtags-mode))
#+END_SRC

** helm-swoop

List match lines to another buffer, which is able to squeeze by any words you input. At the same time, the original buffer's cursor is jumping line to line according to moving up and down the line list.

GitHub: https://github.com/ShingoFukuyama/helm-swoop

#+BEGIN_SRC emacs-lisp
(use-package helm-swoop :ensure t :after (helm))
#+END_SRC

** helm-c-yasnippet

GitHub: https://github.com/emacs-jp/helm-c-yasnippet

#+BEGIN_SRC emacs-lisp
(use-package helm-c-yasnippet
:ensure t
:after (helm yasnippet)
:config
(setq helm-yas-space-match-any-greedy t))
#+END_SRC

** helm-smex

#+BEGIN_SRC emacs-lisp
(use-package helm-smex :ensure t :after (helm))
#+END_SRC

** Setup Helm Keybindings :keybinding:

#+BEGIN_SRC emacs-lisp :tangle no :noweb-ref helm-config
(bind-keys :map helm-map
("TAB" . helm-execute-persistent-action)
("" . helm-execute-persistent-action)
("C-w" . backward-kill-word)
("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)
("M-v" . my/minibuffer-switch-to-vm)
("M-c" . my/minibuffer-switch-to-cluster)
("C-z" . helm-select-action))
#+END_SRC
* Org :org:

#+BEGIN_SRC emacs-lisp :noweb no-export :exports code
(use-package org
:ensure nil ; built-in
:mode (("\\.org\\'" . org-mode)
("\\.org_archive\\'" . org-mode))
:config
(setq org-url-hexify-p nil)
<>)
#+END_SRC

** Basic setup

#+BEGIN_SRC emacs-lisp :tangle no :noweb-ref org-config
;; fontify source code
(setq org-src-fontify-natively t)
;; Use current window when switch to source block
(setq org-src-window-setup 'current-window)
;; Disable prompting to evaluate babel blocks
(setq org-confirm-babel-evaluate nil)
;; Disable add validation link when export to HTML
(setq org-html-validation-link nil)
#+END_SRC

*** Indention setup

Always enable auto indent for org-mode.

#+BEGIN_SRC emacs-lisp
(use-package org-indent
:ensure nil ; build-in
:after (org)
:config
;; Enable `org-indent-mode' by default
(add-hook 'org-mode-hook #'(lambda () (org-indent-mode t))))
#+END_SRC

*** Pretty Bullets

Show org-mode bullets as UTF-8 characters.

GitHub: https://github.com/sabof/org-bullets

#+BEGIN_SRC emacs-lisp
(use-package org-bullets
:ensure t
:after (org)
:config
(add-hook 'org-mode-hook #'(lambda () (org-bullets-mode 1))))
#+END_SRC

*** Setup TODO keywords

#+BEGIN_SRC emacs-lisp :tangle no :noweb-ref org-config
(setq org-todo-keywords '((sequence "TODO(t)" "|" "DONE(d)")
(sequence "WAITING(w)" "|")
(sequence "|" "CANCELED(c)")))
#+END_SRC

*** Enable word-wrap

Call =visual-line-mode= to have soft-wrap.

#+BEGIN_SRC emacs-lisp :tangle no :noweb-ref org-config
(add-hook 'org-mode-hook #'visual-line-mode)
#+END_SRC

** Disable electric-pair for org-mode :electric:pair:

#+begin_src emacs-lisp :tangle no :noweb-ref org-config
(add-hook 'org-mode-hook #'(lambda () (electric-pair-local-mode -1)))
#+end_src

** Extend org-mode's easy templates

org-mode make it easy to insert blocks by typing =>\n %i\n %a")
("j" "Journal" entry (file+datetree "" "Journal") "* %?\nEntered on %U\n %i\n %a")
))
#+END_SRC

** Deft for Note-taking

#+BEGIN_SRC emacs-lisp
(use-package deft
:ensure t
:config
;; default use org-mode
(setq deft-default-extension "org")
;; default directory set to ~/Org
(setq deft-directory "~/Org")
;; Do not make deft automatically save file
(setq deft-auto-save-interval 0)
;; Recursive search
(setq deft-recursive t)

;; setup an minor-mode to quickly kill all deft buffers
(define-minor-mode deft-note-mode "Deft notes" nil " Deft-Notes" nil)
(setq deft-text-mode 'deft-note-mode)

;; Quickly kill deft buffers
(defun my/kill-all-deft-notes ()
(interactive)
(save-excursion
(let ((count 0))
(dolist (buffer (buffer-list))
(set-buffer buffer)
(when (not (eq nil deft-note-mode))
(setq count (1+ count))
(kill-buffer buffer))))))

;; Enable/Disable defts
(defun deft-or-close ()
(interactive)
(if (or (eq major-mode 'deft-mode) (not (eq nil deft-note-mode)))
(progn (my/kill-all-deft-notes) (kill-buffer "*Deft*"))
(deft)))

(defun my/deft-practice ()
"Use deft to quickly see my blog drafts."
(interactive)
(let ((deft-directory "~/Workspace/practice")
(deft-extensions '("md" "org"))))
(deft)))
#+END_SRC

** Make spell-checking tool ignore some org-mode section

see: http://emacs.stackexchange.com/questions/450/intelligent-spell-checking-in-org-mode

#+BEGIN_SRC emacs-lisp :tangle no :noweb-ref org-config
(eval-after-load 'ispell
'(progn
(add-to-list 'ispell-skip-region-alist '(":\\(PROPERTIES\\|LOGBOOK\\):" . ":END:"))
(add-to-list 'ispell-skip-region-alist '("#\\+BEGIN_SRC" . "#\\+END_SRC"))
))
#+END_SRC

** Crypt contents in org-mode

#+BEGIN_SRC emacs-lisp
(use-package org-crypt
:ensure nil
:after (org)
:config
;; Disable `auto-save-mode' for org-mode buffer prior to decrypting an entry.
(setq org-crypt-disable-auto-save t)
;; Auto encrypt when save file
(org-crypt-use-before-save-magic)
;; Encrypt with tagname: `secret'
(setq org-crypt-tag-matcher "secret")
;; Prevent the `secret' tag inherit by child
;; (The child item still will be encrypt)
(setq org-tags-exclude-from-inheritance (quote ("secret")))
;; Use my own password to encrypt
(setq org-crypt-key nil))
#+END_SRC

** Drag-and-drop image to your org-mode file

[[https://github.com/abo-abo/org-download][org-download]] will let you drag-and-drop image to your org-mode file easily.

GitHub: https://github.com/abo-abo/org-download

#+BEGIN_SRC emacs-lisp
(use-package org-download
:ensure t
:config
;; add support to dired
(add-hook 'dired-mode-hook 'org-download-enable))
#+END_SRC

** Setup Org-mode Keybindings :keybinding:

#+BEGIN_SRC emacs-lisp :tangle no :noweb-ref org-config
(bind-keys :map org-mode-map
("M-p" . org-previous-visible-heading)
("M-n" . org-next-visible-heading)
("C-c a" . org-agenda)
("C-c c" . org-capture)
("C-c l" . org-store-link)
("C-c b" . org-metaleft)
("C-c f" . org-metaright)
("C-c p" . org-metaup)
("C-c n" . org-metadown)
("C-c i" . org-insert-link)
("C-c I" . org-toggle-inline-images)
("C-c %" . org-mark-ring-push)
("C-c &" . org-mark-ring-goto)
("C-c C-." . org-babel-remove-result-one-or-many))
#+END_SRC

#+BEGIN_SRC emacs-lisp :tangle no :noweb-ref org-config
(bind-keys :map org-src-mode-map
("C-c C-c" . org-edit-src-exit))
#+END_SRC

* Programming Languages

** PlantUML :plantuml:

GitHub: https://github.com/skuro/plantuml-mode

#+BEGIN_SRC emacs-lisp
(use-package plantuml-mode
:ensure t
:mode ("\\.plantuml\\'")
:init
;; FIXME: setup plantuml jar path
;; FIXME: add org-mode support
)
#+END_SRC

** Bison

[[https://www.gnu.org/software/bison/][Bison]] s a general-purpose parser generator that converts an annotated context-free grammar into a deterministic LR or generalized LR (GLR) parser employing LALR(1) parser tables. As an experimental feature, Bison can also generate IELR(1) or canonical LR(1) parser tables. Once you are proficient with Bison, you can use it to develop a wide range of language parsers, from those used in simple desk calculators to complex programming languages.

Bison is upward compatible with Yacc: all properly-written Yacc grammars ought to work with Bison with no change. Anyone familiar with Yacc should be able to use Bison with little trouble. You need to be fluent in C or C++ programming in order to use Bison. Java is also supported as an experimental feature.

#+BEGIN_SRC emacs-lisp
(use-package bison-mode
:ensure t
:mode ("\\.y\\'" "\\.l\\'" "\\.jison\\'"))
#+END_SRC

** GN

[[https://chromium.googlesource.com/chromium/src/tools/gn/+/48062805e19b4697c5fbd926dc649c78b6aaa138/README.md][GN]] is a meta-build system that generates [[https://chromium.googlesource.com/chromium/src/tools/gn/+/48062805e19b4697c5fbd926dc649c78b6aaa138/NinjaBuild.md][NinjaBuild]] files. This system is widely used on Google's chromium related framework.

Take a look on [[https://gn.googlesource.com/gn/+/refs/heads/main/docs/reference.md][GN reference]] or [[https://chromium.googlesource.com/chromium/src/tools/gn/+/48062805e19b4697c5fbd926dc649c78b6aaa138/docs/quick_start.md][GN Quick Start Guide]] for more info.

#+BEGIN_SRC emacs-lisp
(use-package gn-mode
:ensure t
:mode ("BUILD.gn" "\\.gni?\\'"))
#+END_SRC

** Markdown

[[https://en.wikipedia.org/wiki/Markdown][Markdown]] is a lightweight markup language with plain text formatting syntax designed so that it can be converted to HTML and many other formats using a tool by the same name. Markdown is often used to format readme files, for writing messages in online discussion forums, and to create rich text using a plain text editor.

Here I use [[http://jblevins.org/projects/markdown-mode/][markdown-mode]] to help me integrate markdown with emacs, the README.md is bind to =gfm-mode= for github's markdown flavor.

#+BEGIN_SRC emacs-lisp :noweb no-export :exports code
(use-package markdown-mode
:ensure t
:commands (markdown-mode gfm-mode)
:mode (("README\\.md\\'" . gfm-mode)
("\\.md\\'" . markdown-mode)
("\\.markdown\\'" . markdown-mode))
:init (setq markdown-command "multimarkdown")
:config
<>)
#+END_SRC

*** Syntax highlighting on code blocks

[[http://jblevins.org/log/mmm][Syntax highlighting for code blocks in Emacs Markdown Mode]] give us some hint to use =mmm-mode= syntax highlight code block on markdown-mode.

#+BEGIN_SRC emacs-lisp :tangle no :noweb-ref markdown-config
;; http://jblevins.org/log/mmm
(use-package mmm-mode
:ensure t
:config
(setq mmm-global-mode 'maybe)
(setq mmm-parse-when-idle 't)
(defun my/mmm-markdown-auto-class (lang &optional submode)
"Define a mmm-mode class for LANG in `markdown-mode' using SUBMODE.
If SUBMODE is not provided, use `LANG-mode' by default."
(let ((class (intern (concat "markdown-" lang)))
(submode (or submode (intern (concat lang "-mode"))))
(front (concat "^```" lang "[\n\r]+"))
(back "^```"))
(mmm-add-classes (list (list class :submode submode :front front :back back)))
(mmm-add-mode-ext-class 'markdown-mode nil class)))

;; Mode names that derive directly from the language name
(mapc 'my/mmm-markdown-auto-class
'("awk" "bibtex" "c" "cpp" "css" "html" "latex" "lisp" "makefile"
"markdown" "python" "r" "ruby" "sql" "stata" "xml" "js")))
#+END_SRC

*** Setup Markdown keybinding :keybinding:

#+BEGIN_SRC emacs-lisp :tangle no :noweb-ref markdown-config
(bind-keys :map markdown-mode-map
("C-c i" . markdown-insert-link))

(bind-keys :map gfm-mode-map
("C-c i" . markdown-insert-link))
#+END_SRC

** NASM

#+BEGIN_SRC emacs-lisp
(use-package nasm-mode :ensure t)
#+END_SRC

** TOML

[[https://github.com/toml-lang/toml][TOML]] aims to be a minimal configuration file format that's easy to read due to obvious semantics. TOML is designed to map unambiguously to a hash table. TOML should be easy to parse into data structures in a wide variety of languages.

#+BEGIN_SRC emacs-lisp
(use-package toml-mode
:ensure t
:mode "\\.toml$")
#+END_SRC

** YAML

[[https://en.wikipedia.org/wiki/YAML][YAML]] is a human-readable data serialization language. It is commonly used for configuration files, but could be used in many applications where data is being stored (e.g. debugging output) or transmitted (e.g. document headers). YAML targets many of the same communications applications as XML, but has taken a more minimal approach which intentionally breaks compatibility with SGML.

#+BEGIN_SRC emacs-lisp
(use-package yaml-mode
:ensure t
:mode "\\.yml$")
#+END_SRC

** R

#+BEGIN_SRC emacs-lisp :noweb no-export :exports code
(use-package ess
:ensure t
:mode ("\\.[rR]\\'" . R-mode)
:config
<>)
#+END_SRC

** QML

#+BEGIN_SRC emacs-lisp :noweb no-export :exports code
(use-package qml-mode
:ensure t
:mode "\\.qml$"
:config
<>)
#+END_SRC

*** indent-guide

#+BEGIN_SRC emacs-lisp :tangle no :noweb-ref qml-config
(use-package indent-guide
:ensure t
:config
(add-hook 'qml-mode-hook #'indent-guide-mode))
#+END_SRC

** Vala :vala:

Vala is a new programming language that allows modern programming
techniques to be used to write applications that run on the GNOME
runtime libraries, particularly GLib and GObject.

For more info about vala, please see: [[https://wiki.gnome.org/Projects/Vala/Tutorial][Vala Tutorial]]

#+BEGIN_SRC emacs-lisp :noweb no-export :exports code
(use-package vala-mode
:ensure t
:mode ("\\.vala\\'" "\\.vapi\\'")
:config
<>)
#+END_SRC

** Verilog :verilog:

#+BEGIN_SRC emacs-lisp :noweb no-export :exports code
(use-package verilog-mode
:mode ("\\.v\\'")
:config
<>)
#+END_SRC

#+BEGIN_SRC emacs-lisp :tangle no :noweb-ref verilog-config
(setq verilog-linter "verilator --lint-only")
;; https://github.com/flycheck/flycheck/issues/1250
(setq flycheck-verilog-verilator-executable "/usr/bin/verilator_bin")
#+END_SRC

** Groovy

#+begin_src emacs-lisp :noweb no-export :exports code
(use-package groovy-mode
:mode (("\\.groovy" . groovy-mode)
("/Jenkinsfile" . groovy-mode))
:ensure t)
#+end_src

** Svelete

#+BEGIN_SRC emacs-lisp
(use-package svelte-mode
:ensure t
:mode ("\\.svelte\\'" . svelte-mode))
#+END_SRC

* Configration Files

Since emacs not built-in all configration files syntax highlight support, we need to install manually.

** Docker

#+BEGIN_SRC emacs-lisp
(use-package dockerfile-mode
:ensure t
:mode "Dockerfile\\'")
#+END_SRC

** SSH

#+BEGIN_SRC emacs-lisp
(use-package ssh-config-mode
:ensure t
:mode ((".ssh/config\\'" . ssh-config-mode)
("sshd?_config\\'" . ssh-config-mode)
("known_hosts\\'" . ssh-known-hosts-mode)
("authorized_keys\\'" . ssh-authorized-keys-mode)))
#+END_SRC

** Systemd

#+BEGIN_SRC emacs-lisp
(use-package systemd
:ensure t)
#+END_SRC

** CMake

#+BEGIN_SRC emacs-lisp
(use-package cmake-mode
:ensure t
:mode (("CMakeLists\\.txt\\'" . cmake-mode) ("\\.cmake\\'" . cmake-mode)))
#+END_SRC

#+BEGIN_SRC emacs-lisp
;; cmake-font-lock: emacs font lock rules for CMake
;; https://github.com/Lindydancer/cmake-font-lock
(use-package cmake-font-lock
:ensure t
:config
(autoload 'cmake-font-lock-activate "cmake-font-lock" nil t)
(add-hook 'cmake-mode-hook 'cmake-font-lock-activate))
#+END_SRC

#+RESULTS:
: t

** Meson

#+BEGIN_SRC emacs-lisp
(use-package meson-mode
:ensure t
:mode (("meson\\.build\\'" . meson-mode)))
#+END_SRC

* C/C++ Development :cpp:

#+BEGIN_SRC emacs-lisp :noweb no-export :exports code
(use-package cc-mode
:mode
(("\\.h\\'" . c++-mode)
("\\.c\\'" . c-mode)
("\\.hpp\\'" . c++-mode)
("\\.cpp\\'" . c++-mode)
("\\.cc\\'" . c++-mode))
:config
<>)
#+END_SRC

** ElDoc supports :eldoc:

#+BEGIN_SRC emacs-lisp
(use-package c-eldoc
:ensure t
:config
(add-hook 'c-mode-common-hook
#'(lambda ()
(setq c-eldoc-includes "`pkg-config --cflags --libs` -I./ -I../")
(c-turn-on-eldoc-mode))))
#+END_SRC

** Highlight a few dangerous types in C/C++

[[http://www.emacswiki.org/emacs/CWarnMode][cwarn-mode]] is a minor mode that ca highlight a few dangerous types in C/C++.

By default it highlights:

- Semicolons right after conditions and loops (e.g. ~if (x == y);~)
- Assignments in tests (e.g. ~if (x = y) {~)
- Functions with reference parameters (e.g. ~void funct(string &p) {~)

#+BEGIN_SRC emacs-lisp
(use-package cwarn
:config
(add-hook 'c-mode-common-hook #'(lambda () (cwarn-mode 1))))
#+END_SRC

** Comment #if 0 #endif region

#+BEGIN_SRC emacs-lisp
(defun my/cc-mode/highlight-if-0 ()
"highlight c/c++ #if 0 #endif macros"
(setq cpp-known-face 'default)
(setq cpp-unknown-face 'default)
(setq cpp-known-writable 't)
(setq cpp-unknown-writable 't)
(setq cpp-edit-list '(("0" '(foreground-color . "gray") default both)
("1" default font-lock-comment-face both)))
(cpp-highlight-buffer t))

;; Add to c/c++ mode
(defun my/cc-mode/highlight-if-0-hook ()
(when (or (eq major-mode 'c++-mode) (eq major-mode 'c-mode)
(eq major-mode 'c++-ts-mode) (eq major-mode 'c-ts-mode))
(my/cc-mode/highlight-if-0)))
(add-hook 'after-save-hook #'my/cc-mode/highlight-if-0-hook)
#+END_SRC

** Treat helloWorld as two words :subword:

In most C/C++ project, we naming variable in camelCase, =subword-mode= can help us treat =helloWorld= as two words.

#+BEGIN_SRC emacs-lisp :tangle no :noweb-ref cc-mode-config
;; subword-mode, e.g., someThing is treated as two words
(add-hook 'c-mode-common-hook #'(lambda () (subword-mode 1)))
#+END_SRC

** Auto pair parentheses with electric-pair

#+BEGIN_SRC emacs-lisp
(add-hook 'c-mode-common-hook 'electric-pair-mode)
#+END_SRC

** Add refactor function support

Semantic Refactor is a C/C++ refactoring tool based on Semantic parser framework.

GitHub: https://github.com/tuhdo/semantic-refactor

#+BEGIN_SRC emacs-lisp
(use-package srefactor
:ensure t
:defer t
:after (cc-mode))
#+END_SRC

** Quick switch between header and source file in C/C++

This extension allows to quickly switch between header and a source file with
the same name located in the directory tree or repository. It is an alternatife
to =ff-find-other-file=.

GitHub: https://github.com/fourier/cff

#+BEGIN_SRC emacs-lisp
(use-package cff
:ensure t
:after (cc-mode))
#+END_SRC

** Extra Syntax Highlight

Some syntax highlight may not support in default emacs, set it here.

*** Highlights stdint types

Extra hightlight for =stdint.h=

#+BEGIN_SRC emacs-lisp :tangle no :noweb-ref cc-mode-config
(dolist (m '(c-mode c++-mode))
(font-lock-add-keywords
m
'(("\\<\\(int8_t\\|int16_t\\|int32_t\\|int64_t\\|uint8_t\\|uint16_t\\|uint32_t\\|uint64_t\\)\\>" . font-lock-keyword-face))))
#+END_SRC

*** Modern C++ ~ C++17 font-lock highlighting

#+BEGIN_SRC emacs-lisp
;; adds font-lock highlighting for modern C++ upto C++17
;; https://github.com/ludwigpacifici/modern-cpp-font-lock
(use-package modern-cpp-font-lock
:ensure t
:hook (c++-mode . modern-c++-font-lock-mode)
:after (cc-mode))
#+END_SRC

** Coding Styles

Since C/C++ has too many coding styles, I need to set it up.

*** C
**** General C Coding Style

I always use =linux coding style= for c language by default.

#+BEGIN_SRC emacs-lisp :tangle no :noweb-ref cc-mode-config
(add-hook 'c-mode-hook
#'(lambda ()
(c-set-style "linux")
(setq c-basic-offset 8)
;; Make TAB equivilent to 8 spaces
(setq tab-width 8)))
#+END_SRC

**** Linux Kernel C Coding Style

As part of Linux Kernel developer, I add =linux-kernel= coding style rule, which
use =tabs= as indent and follow linux kernel development rules. Use following
code to make emacs switch to =linux-kernel= style automatically when enter linux
kernel directories.

This coding style is document in https://www.kernel.org/doc/Documentation/CodingStyle.

#+BEGIN_SRC emacs-lisp :tangle no :noweb-ref cc-mode-config
(defun c-lineup-arglist-tabs-only (ignored)
"Line up argument lists by tabs, not spaces"
(let* ((anchor (c-langelem-pos c-syntactic-element))
(column (c-langelem-2nd-pos c-syntactic-element))
(offset (- (1+ column) anchor))
(steps (floor offset c-basic-offset)))
(* (max steps 1)
c-basic-offset)))

;; Add Linux kernel style
(add-hook 'c-mode-common-hook
(lambda ()
(c-add-style "linux-kernel"
'("linux" (c-offsets-alist
(arglist-cont-nonempty
c-lineup-gcc-asm-reg
c-lineup-arglist-tabs-only))))))

(defun linux-kernel-development-setup ()
(let ((filename (buffer-file-name)))
;; Enable kernel mode for the appropriate files
(when (and filename
(or (locate-dominating-file filename "Kbuild")
(locate-dominating-file filename "Kconfig")
(save-excursion (goto-char 0)
(search-forward-regexp "^#include $" nil t))))
(setq indent-tabs-mode t)
(setq tab-width 8)
(setq c-basic-offset 8)
(c-set-style "linux-kernel")
(message "Setting up indentation for the linux kernel"))))

(add-hook 'c-mode-hook 'linux-kernel-development-setup)
#+END_SRC

*** C++

Use my C++ coding style.

#+BEGIN_SRC emacs-lisp :tangle no :noweb-ref cc-mode-config
(add-hook 'c++-mode-hook
'(lambda ()

;; Use stroustrup style
(c-set-style "stroustrup")

;; Setting indentation lvel
(setq c-basic-offset 4)

;; Make TAB equivilent to 4 spaces
(setq tab-width 4)

;; Use spaces to indent instead of tabs.
(setq indent-tabs-mode nil)

;; Indent the continuation by 2
(setq c-continued-statement-offset 2)

;; Brackets should be at same indentation level as the statements they open
;; for example:
;; if (0) becomes if (0)
;; { {
;; ; ;
;; } }
(c-set-offset 'substatement-open 0)

;; make open-braces after a case
(c-set-offset 'case-label '+)

;; Not indent code inside a namespace
;; for example:
;; namespace A {
;;
;; int namespace_global_variable;
;;
;; class Class {
;;
;; Class();
;; //...
;; };
;;
;; }
(c-set-offset 'innamespace 0)
))
#+END_SRC

** Extra commands for c/c++ development

*** kill the function in one command

#+BEGIN_SRC emacs-lisp
(defun my/c-kill-defun ()
"Move backward to the beging of top level declaration and save
this declaration to the kill-ring."
(interactive)
(save-excursion
(kill-region
(progn (c-beginning-of-defun) (point))
(progn (c-end-of-defun) (point)))))
#+END_SRC

*** Use clang-format to format buffer

#+BEGIN_SRC emacs-lisp
;; clang-format: format C/C++ buffers using clang-format
;; https://github.com/emacsorphanage/clang-format
(use-package clang-format
:ensure t)
#+END_SRC

** Setup C/C++ Keybinding

#+BEGIN_SRC emacs-lisp :tangle no :noweb-ref cc-mode-config
(bind-keys :map c-mode-base-map
;;("C-c '" . my/narrow-or-widen-dwim)
("C-c C-c" . compile)
("C-c C-g" . gdb)
("C-c C-o" . cff-find-other-file))

;; Some keys may override global map add here
(bind-keys :map c-mode-base-map
("M-." . helm-gtags-dwim)
("M-," . helm-gtags-pop-stack))
#+END_SRC

* Lisp Development

Though =LISP= has many dialet, it still is the best programming language I ever met.

** Emacs Lisp

#+BEGIN_SRC emacs-lisp :noweb no-export
(use-package elisp-mode
:ensure nil ; built-in
:config
<>)
#+END_SRC

*** Interactive macro-expander for Emacs

=macrostep= is an Emacs minor mode for interactively stepping through the expansion of macros in Emacs Lisp source code. It lets you see exactly what happens at each step of the expansion process by pretty-printing the expanded forms inline in the source buffer, which is temporarily read-only while macro expansions are visible. You can expand and collapse macro forms one step at a time, and evaluate or instrument the expansions for debugging with Edebug as normal (but see “Bugs and known limitations”, below). Single-stepping through the expansion is particularly useful for debugging macros that expand into another macro form. These can be difficult to debug with Emacs’ built-in macroexpand, which continues expansion until the top-level form is no longer a macro call.

GitHub: https://github.com/joddie/macrostep

#+BEGIN_SRC emacs-lisp :tangle no :noweb-ref emacs-lisp-mode-config
(use-package macrostep
:ensure t)
#+END_SRC

*** Additional flavour to emacs-lisp programming

el-spice is a minor mode that provides additional configuration to make
programming in Emacs Lisp more enjoyable.

GitHub: https://github.com/vedang/el-spice

#+BEGIN_SRC emacs-lisp :tangle no :noweb-ref emacs-lisp-mode-config
(use-package el-spice
:ensure t)
#+END_SRC

*** Add eldoc support :eldoc:

#+BEGIN_SRC emacs-lisp :tangle no :noweb-ref emacs-lisp-mode-config
(use-package eldoc
:ensure t
:config
(add-hook 'emacs-lisp-mode-hook
'(lambda ()
;; enable eldoc
(turn-on-eldoc-mode)
;; fix for paredit if exist
(eval-after-load 'paredit
'(progn
(eldoc-add-command 'paredit-backward-delete
'paredit-close-round))))))
#+END_SRC

*** Check paren on save

#+BEGIN_SRC emacs-lisp :tangle no :noweb-ref emacs-lisp-mode-config
(defun my/elisp/check-parens-on-save ()
"Run `check-parens' when the current buffer is saved."
(add-hook 'after-save-hook #'check-parens nil 'make-it-local))

(add-hook 'emacs-lis-mode
(lambda () (my/emacs-lisp/enable-check-parens-on-save)))
#+END_SRC

*** On-the-fly evaluation/substitution of emacs lisp code

[[https://github.com/Fuco1/litable][litable]] keeps a list of pure functions as a safeguard for unwanted evaluations.
A function must first be accepted into this list (using =M-x litable-accept-as-pure=)
before it can be evaluated on-the-fly.

You should take care of what function you accept as pure to avoid any
unfortunate accidents. Also, note that the pure functions list persists across
sessions.

GitHub: https://github.com/Fuco1/litable

#+BEGIN_SRC emacs-lisp :tangle no :noweb-ref emacs-lisp-mode-config
(use-package litable
:ensure t
:config
;; Save cache file to `user-cache-direcotry'
(setq litable-list-file (concat user-cache-directory ".litable-lists.el"))
;; Enable litable-mode globally
(litable-mode))
#+END_SRC

*** Display ^L glyphs as horizontal lines

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

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

#+BEGIN_SRC emacs-lisp :tangle no :noweb-ref emacs-lisp-mode-config
(use-package page-break-lines
:ensure t
:config
;; enable globally
(global-page-break-lines-mode 1))
#+END_SRC

*** Remove *.elc when save

#+BEGIN_SRC emacs-lisp :tangle no :noweb-ref emacs-lisp-mode-config
(defun my/remove-elc-on-save ()
"If you're saving an elisp file, likely the .elc is no longer valid."
(make-local-variable 'after-save-hook)
(add-hook 'after-save-hook
(lambda ()
(if (file-exists-p (concat buffer-file-name "c"))
(delete-file (concat buffer-file-name "c"))))))

(add-hook 'emacs-lisp-mode-hook 'my/remove-elc-on-save)
#+END_SRC

*** Setup Emacs-Lisp Keybindings :keybinding:

#+BEGIN_SRC emacs-lisp :tangle no :noweb-ref emacs-lisp-mode-config
(bind-keys :map emacs-lisp-mode-map
;; ("C-c '" . my/narrow-or-widen-dwim)
)
#+END_SRC

* Blogging

I now use [[https://hexo.io][Hexo]] with my fork of [[http://github.com/coldnew/hexo-renderer-org][hexo-renderer-org]] for blogging, [[http://github.com/kuanyui/hexo.el][hexo.el]] is a nice plugin to control hexo blog post in Emacs.

However, I use my fork of [[https://github.com/coldnew/hexo.el][hexo.el]] since threre's some feature I want to but not exist in upstream.

#+BEGIN_SRC emacs-lisp
;; Use my fork of hexo.el, save to `modules/hexo.el'
(add-to-list 'load-path
(directory-file-name (concat user-modules-directory "hexo.el")))
#+END_SRC

#+BEGIN_SRC emacs-lisp
(use-package hexo
:ensure t
:config

(defun hexo-my-blog ()
"My blog with hexo."
(interactive)
(hexo "~/Workspace/blog/"))

(defun hexo-my-draft ()
"My blog draft with hexo."
(interactive)
(hexo "~/Workspace/draft/"))

(defun hexo-my-draft ()
"My blog with hexo."
(interactive)
(hexo "~/Workspace/draft/"))
)
#+END_SRC

* Version Control

** Disable all vc-mode feature

Emacs's builtin =vc-mode= is not really useful, and will make emacs slow when edit file over =sshfs=.

I disable all setting handled by vc-mode here since I only use git and don't want vc-mode bother with other version control system.

#+BEGIN_SRC emacs-lisp
(setq vc-handled-backends nil)
#+END_SRC

** Git

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

GitHub: https://github.com/magit/magit

#+BEGIN_SRC emacs-lisp :noweb no-export :exports code
(use-package magit
:ensure t
:config
<>)
#+END_SRC

*** Setup default commit arguments

I always add =sign-off= to the commit and make magit verbose.

#+BEGIN_SRC emacs-lisp :tangle no :noweb-ref magit-config
(setq magit-commit-arguments '("--verbose" "--signoff"))
#+END_SRC

*** Enable diff-highlight

If you use git in command line, you can turn on diff-highlight by following command

#+BEGIN_SRC sh :tangle no
git config --global core.pager "diff-highlight | less --tabs=4 -RFX"
#+END_SRC

With magit, we can use =M-x magit-toggle-diff-refine-hunk= or make it enable by default:

#+BEGIN_SRC emacs-lisp
(setq magit-diff-refine-hunk 'all)
#+END_SRC

*** Add support for git configuration files

git-modes contains gitignore, gitconfig, gitattributes related config files support, we don't need to load it separately.

GitHub: https://github.com/magit/git-modes

#+BEGIN_SRC emacs-lisp
(use-package git-modes :ensure t)
#+END_SRC

*** Add GitGutter on fringe

GitHub: https://github.com/syohex/emacs-git-gutter-fringe

#+BEGIN_SRC emacs-lisp
(use-package git-gutter-fringe
:ensure t
:if window-system ; git-gutter-fringe only work on GUI
:config
;; enable globally
(git-gutter-mode))
#+END_SRC

* IDE Features

emacs has some IDE feature, add here.

** flycheck

#+BEGIN_SRC emacs-lisp
(use-package flycheck
:ensure t
:config
;; enable globally
(global-flycheck-mode))
#+END_SRC

** treesit

https://archive.casouri.cc/note/2023/tree-sitter-starter-guide/index.html

#+BEGIN_SRC emacs-lisp
(use-package treesit
:ensure nil ; build-in since emacs-29.1
:when (and (fboundp 'treesit-available-p)
(treesit-available-p))
:config (setq treesit-font-lock-level 4)
:init
(setq treesit-language-source-alist
'((bash . ("https://github.com/tree-sitter/tree-sitter-bash"))
(c . ("https://github.com/tree-sitter/tree-sitter-c"))
(cpp . ("https://github.com/tree-sitter/tree-sitter-cpp"))
(css . ("https://github.com/tree-sitter/tree-sitter-css"))
(cmake . ("https://github.com/uyha/tree-sitter-cmake"))
(csharp . ("https://github.com/tree-sitter/tree-sitter-c-sharp.git"))
(dockerfile . ("https://github.com/camdencheek/tree-sitter-dockerfile"))
(elisp . ("https://github.com/Wilfred/tree-sitter-elisp"))
(go . ("https://github.com/tree-sitter/tree-sitter-go"))
(gomod . ("https://github.com/camdencheek/tree-sitter-go-mod.git"))
(html . ("https://github.com/tree-sitter/tree-sitter-html"))
(java . ("https://github.com/tree-sitter/tree-sitter-java.git"))
(javascript . ("https://github.com/tree-sitter/tree-sitter-javascript"))
(json . ("https://github.com/tree-sitter/tree-sitter-json"))
(lua . ("https://github.com/Azganoth/tree-sitter-lua"))
(make . ("https://github.com/alemuller/tree-sitter-make"))
(markdown . ("https://github.com/MDeiml/tree-sitter-markdown" nil "tree-sitter-markdown/src"))
(ocaml . ("https://github.com/tree-sitter/tree-sitter-ocaml" nil "ocaml/src"))
(org . ("https://github.com/milisims/tree-sitter-org"))
(python . ("https://github.com/tree-sitter/tree-sitter-python"))
(php . ("https://github.com/tree-sitter/tree-sitter-php"))
(typescript . ("https://github.com/tree-sitter/tree-sitter-typescript" nil "typescript/src"))
(tsx . ("https://github.com/tree-sitter/tree-sitter-typescript" nil "tsx/src"))
(ruby . ("https://github.com/tree-sitter/tree-sitter-ruby"))
(rust . ("https://github.com/tree-sitter/tree-sitter-rust"))
(sql . ("https://github.com/m-novikov/tree-sitter-sql"))
(vue . ("https://github.com/merico-dev/tree-sitter-vue"))
(yaml . ("https://github.com/ikatyang/tree-sitter-yaml"))
(toml . ("https://github.com/tree-sitter/tree-sitter-toml"))
(zig . ("https://github.com/GrayJack/tree-sitter-zig"))))
(add-to-list 'major-mode-remap-alist '(sh-mode . bash-ts-mode))
(add-to-list 'major-mode-remap-alist '(c-mode . c-ts-mode))
(add-to-list 'major-mode-remap-alist '(c++-mode . c++-ts-mode))
(add-to-list 'major-mode-remap-alist '(c-or-c++-mode . c-or-c++-ts-mode))
(add-to-list 'major-mode-remap-alist '(css-mode . css-ts-mode))
(add-to-list 'major-mode-remap-alist '(js-mode . js-ts-mode))
(add-to-list 'major-mode-remap-alist '(java-mode . java-ts-mode))
(add-to-list 'major-mode-remap-alist '(js-json-mode . json-ts-mode))
(add-to-list 'major-mode-remap-alist '(makefile-mode . cmake-ts-mode))
(add-to-list 'major-mode-remap-alist '(python-mode . python-ts-mode))
(add-to-list 'major-mode-remap-alist '(ruby-mode . ruby-ts-mode))
(add-to-list 'major-mode-remap-alist '(conf-toml-mode . toml-ts-mode))
(add-to-list 'auto-mode-alist '("\\(?:Dockerfile\\(?:\\..*\\)?\\|\\.[Dd]ockerfile\\)\\'" . dockerfile-ts-mode))
(add-to-list 'auto-mode-alist '("\\.go\\'" . go-ts-mode))
(add-to-list 'auto-mode-alist '("/go\\.mod\\'" . go-mod-ts-mode))
(add-to-list 'auto-mode-alist '("\\.rs\\'" . rust-ts-mode))
(add-to-list 'auto-mode-alist '("\\.ts\\'" . typescript-ts-mode))
(add-to-list 'auto-mode-alist '("\\.y[a]?ml\\'" . yaml-ts-mode)))
#+END_SRC

* Snippets :yasnippet:

#+BEGIN_SRC emacs-lisp :noweb no-export :exports code
(use-package yasnippet
:ensure t
:mode ("emacs.+/snippets/" . snippet-mode)
:config
;; enable yasnippet globally
(yas-global-mode 1)
;; extra yasnipet configs
<>)
#+END_SRC

** Setup yasnippet prompt method

#+BEGIN_SRC emacs-lisp :tangle no :noweb-ref yasnippet-config
(setq yas-prompt-functions '(yas-dropdown-prompt
yas-completing-prompt
yas-ido-prompt))
#+END_SRC

** Setup yasnippet snippet dirs

I put my snippets in =~/.emacs.d/snippets=, add it to =yas/snippet-dirs= to make yasnippet can find the snippets.

You can use =yas-new-snippet= to create your new snippet file.

#+BEGIN_SRC emacs-lisp :tangle no :noweb-ref yasnippet-config
(let ((my-snippet-dir (concat user-emacs-directory "snippets")))
(if (and (file-exists-p my-snippet-dir)
(not (member my-snippet-dir yas/snippet-dirs)))
(add-to-list 'yas-snippet-dirs my-snippet-dir)))
#+END_SRC

** Prevent yasnippet conflict with term-mode

#+BEGIN_SRC emacs-lisp :tangle no :noweb-ref yasnippet-config
(add-hook 'term-mode-hook (lambda() (yas-minor-mode -1)))
#+END_SRC

** Implement org-mode's easy-template like function

I really like org-mode's =easy-template= function, so I implement one
called =major-mode-expand= which will let you use easy-template like
function in any major-mode.

#+BEGIN_SRC emacs-lisp :tangle no :noweb-ref yasnippet-config
(defadvice yas-expand (around major-mode-expand activate)
"Try to complete a structure template before point like org-mode does.
This looks for strings like \"j (Vim)=, or =(M-x) import-js-import (Emacs)=.

GitHub: https://github.com/trotzig/import-js

#+BEGIN_SRC emacs-lisp
(use-package import-js :ensure t)
#+END_SRC

** json

#+BEGIN_SRC emacs-lisp
(use-package json-mode :ensure t
:mode "\\.json\\'")
#+END_SRC

#+BEGIN_SRC emacs-lisp
(use-package json-reformat :ensure t :commands json-reformat-region)
#+END_SRC

#+BEGIN_SRC emacs-lisp
(use-package flymake-json :ensure t
:config
(add-hook 'json-mode-hook (lambda () (flymake-json-load))))
#+END_SRC

** po

#+BEGIN_SRC emacs-lisp
(use-package po-mode :ensure t
:mode "\\.po\\'\\|\\.po\\."
:config

;; To use the right coding system automatically under Emacs 20 or newer,
;; also add:
(when (require 'po nil 'noerror)
(modify-coding-system-alist 'file "\\.po\\'\\|\\.po\\."
'po-find-file-coding-system))
)
#+END_SRC

** python

#+BEGIN_SRC emacs-lisp
(use-package python
:mode (("SCons\\(truct\\|cript\\)\\'" . python-mode)
("DEPS" . python-mode)))
#+END_SRC

** ruby

#+BEGIN_SRC emacs-lisp
(use-package ruby-mode
:ensure nil ; built-in
:mode (("Gemfile\\'" . ruby-mode)
("Kirkfile\\'" . ruby-mode)
("Rakefile\\'" . ruby-mode)
("Vagrantfile\\'" . ruby-mode)
("\\.builder\\'" . ruby-mode)
("\\.gemspec\\'" . ruby-mode)
("\\.irbrc\\'" . ruby-mode)
("\\.pryrc\\'" . ruby-mode)
("\\.rake\\'" . ruby-mode)
("\\.rjs\\'" . ruby-mode)
("\\.ru\\'" . ruby-mode)
("\\.rxml\\'" . ruby-mode))
:config
;; We never want to edit Rubinius bytecode
(add-to-list 'completion-ignored-extensions ".rbc"))
#+END_SRC
** go

#+BEGIN_SRC emacs-lisp :noweb no-export
(use-package go-mode
:ensure t
:config
<>)
#+END_SRC

*** Auto completion support

#+BEGIN_SRC emacs-lisp :noweb-ref go-mode-config
(use-package company-go
:ensure t
:config
(defun my/setup-go-mode-company-go ()
"Hook for running on company-go"
;; we only want to use company-go - it's so accurate we won't need
;; any other completion engines
(set (make-local-variable 'company-backends) '(company-go)))
(add-hook 'go-mode-hook 'my/setup-go-mode-company-go))
#+END_SRC

*** Use gofmt fotmat codes before save

#+BEGIN_SRC emacs-lisp :tangle no :noweb-ref go-mode-config
(defun my/setup-go-mode-gofmt-hook ()
;; Use goimports instead of go-fmt
(setq gofmt-command "goimports")
;; Call Gofmt before saving
(add-hook 'before-save-hook 'gofmt-before-save))
(add-hook 'go-mode-hook 'my/setup-go-mode-gofmt-hook)
#+END_SRC

*** Setup Go Keybinding :keybinding:

#+BEGIN_SRC emacs-lisp :tangle no :noweb-ref go-mode-config
(bind-keys :map go-mode-map
("M-." . godef-jump))
#+END_SRC

** nxml

#+BEGIN_SRC emacs-lisp
(use-package nxml-mode
:ensure nil ; emacs built-in
:mode (("\\.plist\\'" . nxml-mode)
("\\.rss\\'" . nxml-mode)
("\\.svg\\'" . nxml-mode)
("\\.xml\\'" . nxml-mode)
("\\.xsd\\'" . nxml-mode)
("\\.xslt\\'" . nxml-mode)
("\\.pom$" . nxml-mode))
:config
;; Any file start with xml will be treat as nxml-mode
(add-to-list 'magic-mode-alist '("<\\?xml" . nxml-mode))
;; Use nxml-mode instead of sgml, xml or html mode.
(mapc
(lambda (pair)
(if (or (eq (cdr pair) 'xml-mode)
(eq (cdr pair) 'sgml-mode))
(setcdr pair 'nxml-mode)))
auto-mode-alist))
#+END_SRC

* TODO LISP Development :lisp:

Though =LISP= has many dialet, it still is the best programming
language I ever met.

** Plugins

Common setup for LISP development.

*** lispy

This package reimagines Paredit - a popular method to navigate and edit LISP code in Emacs.

GitHub: https://github.com/abo-abo/lispy

For more info to control lispy, please refer: http://oremacs.com/lispy/

#+BEGIN_SRC emacs-lisp
(use-package lispy
:ensure t
:config

(defun my/up-list (&optional arg)
"My special lisp moving stragedy."
(interactive)
(or arg (setq arg -1))
(condition-case ex
(up-list arg)
('error (progn
(lispy-backward arg)
(beginning-of-line)
(up-list arg)))))

(defun my/down-list (&optional arg)
"My special lisp moving stragedy."
(interactive)
(or arg (setq arg 1))
(condition-case ex
(down-list arg)
('error (progn
(lispy-forward arg)
(end-of-line)
(down-list arg)))))

;; My special hack for lispy-mode
(defun my/lispy-mode ()
(lispy-mode 1)
;; `M-m' is preserved for mode setting
(define-key lispy-mode-map (kbd "M-m") nil)
;; `M-s' is for my search command, rebind to `C-c s'
(define-key lispy-mode-map (kbd "M-s") nil)
(define-key lispy-mode-map (kbd "C-c s") 'lispy-splice)
;; `[' and `]' just insert them
(define-key lispy-mode-map (kbd "[") 'lispy-open-square)
(define-key lispy-mode-map (kbd "]") 'lispy-close-square)
;; My special lisp moving cmd
(define-key lispy-mode-map (kbd "C-M-f") 'my/down-list)
(define-key lispy-mode-map (kbd "C-M-b") 'my/up-list))

(add-hook 'emacs-lisp-mode-hook #'my/lispy-mode)
(add-hook 'lisp-interaction-mode-hook #'my/lispy-mode)
(add-hook 'clojure-mode-hook #'my/lispy-mode)
(add-hook 'scheme-mode-hook #'my/lispy-mode)
(add-hook 'lisp-mode-hook #'my/lispy-mode))
#+END_SRC
*** indent-guide

#+BEGIN_SRC emacs-lisp
(use-package indent-guide
:ensure t
:config
(add-hook 'emacs-lisp-mode-hook #'indent-guide-mode)
(add-hook 'lisp-interaction-mode-hook #'indent-guide-mode)
(add-hook 'clojure-mode-hook #'indent-guide-mode)
(add-hook 'scheme-mode-hook #'indent-guide-mode)
(add-hook 'lisp-mode-hook #'indent-guide-mode))
#+END_SRC

*** Prettify symbols

Show lambda as λ.

#+BEGIN_SRC emacs-lisp
(global-prettify-symbols-mode 1)
#+END_SRC

* Web Development :web:

#+BEGIN_SRC emacs-lisp
(use-package web-mode
:ensure t
:mode (("\\.html?\\'" . web-mode)
("\\.ejs?\\'" . web-mode)))
#+END_SRC

** CSS :css:

#+BEGIN_SRC emacs-lisp
(use-package css-mode
:ensure nil ; built-in
:mode "\\.css\\'")
#+END_SRC

*** Add support for eldoc :eldoc:

#+BEGIN_SRC emacs-lisp
(use-package css-eldoc
:ensure t
:config
(add-hook 'css-mode-hook 'turn-on-css-eldoc)
(add-hook 'scss-mode-hook 'turn-on-css-eldoc)
(add-hook 'less-css-mode-hook 'turn-on-css-eldoc))
#+END_SRC

** Less :less:

#+BEGIN_SRC emacs-lisp
(use-package less-css-mode
:ensure t
:mode ("\\.less$" . less-css-mode))
#+END_SRC

** SCSS :css:scss:

#+BEGIN_SRC emacs-lisp
(use-package scss-mode
:ensure t
:mode "\\.scss\\'"
:config
;; dont' build scss to css after save file
(setq scss-compile-at-save nil))
#+END_SRC

** mustache :mustache:

Sometimes we will use [[https://mustache.github.io/][mustache]] as template system, [[https://github.com/mustache/emacs][mustache-mode]] is a nice
helper.

GitHub: https://github.com/mustache/emacs

#+BEGIN_SRC emacs-lisp
(use-package mustache-mode :mode "\\.mustache$" :ensure t)
#+END_SRC

** Use emmet-mode to add Zen Coding support

[[https://github.com/smihica/emmet-mode][emmet-mode]] is a fork of [[https://github.com/rooney/zencoding][zencoding-mode]] which add minor mode providing support
for Zen Coding by producing HTML from CSS-like selectors.

GitHub: https://github.com/smihica/emmet-mode

#+BEGIN_SRC emacs-lisp :tangle no
(use-package emmet-mode :ensure t
:config
(progn
;; Following mode support emmet-mode
(add-hook 'html-mode-hook 'emmet-mode)
(add-hook 'sgml-mode-hook 'emmet-mode)
(add-hook 'nxml-mode-hook 'emmet-mode)
(add-hook 'css-mode-hook 'emmet-mode)

;; Move cursor between quotes after expand
(add-hook 'emmt-mode-hook
'(lambda()
(setq emmet-move-cursor-between-quotes t)))

;; Make tab can also expand emmt instead of use yasnippet directly
(define-key emmt-mode-keymap (kbd "TAB") 'emmt-expand-yas)
(define-key emmt-mode-keymap (kbd "") 'emmt-expand-yas)))
#+END_SRC

* Terminal Emulator :term:

** ansi-term

*** Close ansi-term buffer after exit

After the ansi-term process ends it should leaves a buffer.

#+BEGIN_SRC emacs-lisp
(defadvice term-handle-exit (after kill-buffer-after-exit activate)
"Kill the term buffer if the process finished."
(kill-buffer (current-buffer)))
#+END_SRC

** Eshell :eshell:

eshell is not really a system shell, it's written in pure lisp. What I
like is it fully integrated with emacs.

#+BEGIN_SRC emacs-lisp :noweb no-export :exports code
(use-package eshell
:config
;; extra eshell configs
<>)
#+END_SRC

*** Use bash like prompt with color

#+BEGIN_SRC emacs-lisp :tangle no :noweb-ref eshell-config
;; Make eshell prompt look likes default bash prompt
(setq eshell-prompt-function
'(lambda ()
(concat
user-login-name "@" system-name " "
(if (search (directory-file-name (expand-file-name (getenv "HOME"))) (eshell/pwd))
(replace-regexp-in-string (expand-file-name (getenv "HOME")) "~" (eshell/pwd))
(eshell/pwd))
(if (= (user-uid) 0) " # " " $ "))))
#+END_SRC

#+BEGIN_SRC emacs-lisp :tangle no :noweb-ref eshell-config
;; Add color for eshell prompt like Gentoo does
(defun colorfy-eshell-prompt ()
(let* ((mpoint)
(user-string-regexp (concat "^" user-login-name "@" (system-name))))
(save-excursion
(goto-char (point-min))
(while (re-search-forward (concat user-string-regexp ".*[$#]") (point-max) t)
(setq mpoint (point))
(overlay-put (make-overlay (pos-bol) mpoint) 'face '(:foreground "dodger blue")))
(goto-char (point-min))
(while (re-search-forward user-string-regexp (point-max) t)
(setq mpoint (point))
(overlay-put (make-overlay (pos-bol) mpoint) 'face '(:foreground "green3"))))))
;; Make eshell prompt more colorful
(add-hook 'eshell-output-filter-functions 'colorfy-eshell-prompt)
#+END_SRC

*** Use ansi-term to render visual commands

#+BEGIN_SRC emacs-lisp :tangle no :noweb-ref eshell-config
(setq eshell-visual-commands
'("less" "tmux" "htop" "top" "bash" "zsh" "fish" "ssh" "tail"
"vi" "vim" "screen" "less" "more" "lynx" "ncftp" "pine" "tin"
"nmtui" "alsamixer"))

(setq eshell-visual-subcommands
'(("git" "log" "diff" "show")))
#+END_SRC

*** Add autojump command

[[https://github.com/coldnew/eshell-autojump][Eshell Autojump]] is an [[https://github.com/joelthelion/autojump][autojump]] like command written in pure elisp,
which add a =j= command to let you jump to folder you has been access.

GitHub: https://github.com/coldnew/eshell-autojump

#+BEGIN_SRC emacs-lisp
(use-package eshell-autojump :ensure t)
#+END_SRC

*** Fish-like history autosuggestions in eshell

#+BEGIN_SRC emacs-lisp
(use-package esh-autosuggest
:hook (eshell-mode . esh-autosuggest-mode)
:ensure t)
#+END_SRC

*** Eshell commands setup

**** ..

#+BEGIN_SRC emacs-lisp
(defun eshell/.. (&optional level)
"Go up LEVEL directories"
(interactive)
(let ((level (or level 1)))
(eshell/cd (make-string (1+ level) ?.))
(eshell/ls)))
#+END_SRC

**** clear

#+BEGIN_SRC emacs-lisp
(defun eshell/clear ()
"Clears the shell buffer ala Unix's clear or DOS' cls"
;; the shell prompts are read-only, so clear that for the duration
(let ((inhibit-read-only t))
;; simply delete the region
(delete-region (point-min) (point-max))))
#+END_SRC

**** emacs

#+BEGIN_SRC emacs-lisp
(defun eshell/emacs (&rest args)
"Open a file in emacs. Some habits die hard."
(if (null args)
;; If I just ran "emacs", I probably expect to be launching
;; Emacs, which is rather silly since I'm already in Emacs.
;; So just pretend to do what I ask.
(bury-buffer)
;; We have to expand the file names or else naming a directory in an
;; argument causes later arguments to be looked for in that directory,
;; not the starting directory
(mapc #'find-file (mapcar #'expand-file-name (flatten-tree (reverse args))))))

(defalias 'eshell/e 'eshell/emacs)
#+END_SRC

**** unpack

#+BEGIN_SRC emacs-lisp
(defun eshell/unpack (file)
(let ((command (cl-some (lambda (x)
(if (string-match-p (car x) file)
(cadr x)))
'((".*\.tar.bz2" "tar xjf")
(".*\.tar.gz" "tar xzf")
(".*\.bz2" "bunzip2")
(".*\.rar" "unrar x")
(".*\.gz" "gunzip")
(".*\.tar" "tar xf")
(".*\.tbz2" "tar xjf")
(".*\.tgz" "tar xzf")
(".*\.zip" "unzip")
(".*\.Z" "uncompress")
(".*" "echo 'Could not unpack the file:'")))))
(eshell-command-result (concat command " " file))))
#+END_SRC

*** Setup Keybindings :keybinding:

#+BEGIN_SRC emacs-lisp :tangle no :noweb-ref eshell-config
;; FIXME: why this will still global-map ?
;; (bind-keys :map eshell-mode-map
;; ("C-u" . eshell-kill-input))

(add-hook 'eshell-mode-hook
(lambda ()
(define-key eshell-mode-map (kbd "C-u") 'eshell-kill-input)))
#+END_SRC

* Window Management :window:

** winner-mode :winner:

#+BEGIN_SRC emacs-lisp
(use-package winner ; builtin
:commands (winner-undo winner-redo)
:config
;; I use my own keymap for winner-mode
(setq winner-dont-bind-my-keys t)
;; Start winner-mode globally
(winner-mode t))
#+END_SRC

** eyebrowse

=eyebrowse= is a global minor mode for Emacs that allows you to manage
your window configurations in a simple manner, just like tiling window
managers like i3wm with their workspaces do. It displays their current
state in the modeline by default. The behaviour is modeled after
[[http://ranger.nongnu.org/][ranger]], a file manager written in Python.

GitHub: https://github.com/wasamasa/eyebrowse

#+BEGIN_SRC emacs-lisp
(use-package eyebrowse
:ensure t
:config
;; enable eyebrowse globally
(eyebrowse-mode t))
#+END_SRC

** window-numbering

Numbered window shortcuts for Emacs.

Enable =window-numbering-mode= and use =M-1= through =M-0= to navigate.

If you want to affect the numbers, use window-numbering-before-hook or
window-numbering-assign-func. For instance, to always assign the
calculator window the number 9, add the following to your .emacs:

#+BEGIN_SRC emacs-lisp :tangle no
(setq window-numbering-assign-func
(lambda () (when (equal (buffer-name) "*Calculator*") 9)))
#+END_SRC

GitHub: https://github.com/nschum/window-numbering.el

#+BEGIN_SRC emacs-lisp
(use-package window-numbering
:ensure t)
#+END_SRC

* Keybindings :keybinding:

** Global Keybinding

#+BEGIN_SRC emacs-lisp
(bind-keys :map global-map
("C-x C-s" . my/save-buffer-always))
#+END_SRC

** Normal State

#+BEGIN_SRC emacs-lisp :tangle no :noweb-ref evil-keybindings
(evil-define-key 'normal my-editor-map
(kbd "C-x C-f") 'helm-find-files
(kbd "C-x C-q") 'read-only-mode
(kbd "C-x M-1") 'deft-or-close
(kbd "C-x M-2") 'eshell
(kbd "C-x M-3") 'mu4e
(kbd "C-x M-4") 'erc-start-or-switch
(kbd "C-x vl") 'magit-log
(kbd "C-x vp") 'magit-push
(kbd "C-x vs") 'magit-status
(kbd "C-x b") 'helm-buffers-list
(kbd "M-[") 'winner-undo
(kbd "M-]") 'winner-redo
(kbd "M-x") 'helm-M-x
(kbd "M-s") 'helm-occur
(kbd "C-x C-o") 'other-frame
(kbd "M-o") 'other-window)
#+END_SRC

** Insert State

#+BEGIN_SRC emacs-lisp :tangle no :noweb-ref evil-keybindings
(evil-define-key 'insert my-editor-map
(kbd "") 'hungry-delete-backward
(kbd "C-;") 'iedit-mode
(kbd "C-d") 'hungry-delete-forward
(kbd "C-l") 'hungry-delete-backward
(kbd "C-n") 'evil-next-line
(kbd "C-o") 'evil-execute-in-normal-state
(kbd "C-p") 'evil-previous-line
(kbd "C-v") 'set-mark-mode/rectangle-mark-mode
(kbd "C-w") 'backward-kill-word
(kbd "C-x C-f") 'helm-find-files
(kbd "C-x C-n") 'company-complete
(kbd "C-x C-o") 'other-frame
(kbd "C-x C-q") 'read-only-mode
(kbd "C-x M-1") 'deft-or-close
(kbd "C-x M-2") 'eshell
(kbd "C-x M-3") 'mu4e
(kbd "C-x M-4") 'erc-start-or-switch
(kbd "C-x T") 'sane-term
(kbd "C-x b") 'helm-buffers-list
(kbd "C-x t") 'sane-term
(kbd "C-x vl") 'magit-log
(kbd "C-x vp") 'magit-push
(kbd "C-x vs") 'magit-status
(kbd "M-") 'insert-U200B-char
(kbd "M-[") 'winner-undo
(kbd "M-]") 'winner-redo
(kbd "M-s") 'helm-occur
(kbd "M-v") 'er/expand-region
(kbd "M-x") 'helm-M-x
(kbd "M-y") 'helm-show-kill-ring
(kbd "M-y") 'helm-show-kill-ring
(kbd "M-z") 'zzz-to-char
(kbd "s-") 'insert-empty-line
(kbd "s-") 'insert-U200B-char
(kbd "C-x C-d") 'dired
;; (kbd "M-o") 'other-window
;; (kbd "TAB") 'yas/expand
)
#+END_SRC

** Space State

For =space= state, I use evil-leader to achive this goal.

#+BEGIN_SRC emacs-lisp :tangle no :noweb-ref evil-leader-keybindings
(evil-leader/set-leader "")
#+END_SRC

#+BEGIN_SRC emacs-lisp :tangle no :noweb-ref evil-leader-keybindings
(evil-leader/set-key
"1" 'select-window-1
"2" 'select-window-2
"3" 'select-window-3
"4" 'select-window-4
"5" 'select-window-5
"6" 'select-window-6
"7" 'select-window-7
"8" 'select-window-8
"9" 'select-window-9
"0" 'select-window-0)
#+END_SRC

** Ex Command

#+BEGIN_SRC emacs-lisp :tangle no :noweb-ref evil-ex-commands
(evil-ex-define-cmd "ag" 'helm-ag)
(evil-ex-define-cmd "agi[nteractive]" 'helm-do-ag)
(evil-ex-define-cmd "google" 'helm-google)
(evil-ex-define-cmd "google-suggest" 'helm-google-suggest)
(evil-ex-define-cmd "gtag" 'ggtags-create-tags)
(evil-ex-define-cmd "howdoi" 'howdoi-query)
#+END_SRC

* End of configuration

Oh YA!! We finish loading emacs configuration :)

In the end of configuration, I'll load my private config from =~/.personal.el=,
which contains something like password or account settings.

#+BEGIN_SRC emacs-lisp
(let ((secret "~/.personal.el"))
(when (file-exists-p secret) (load-file secret)))
#+END_SRC