This is my emacs configuration, I use ONE single org-mode file to write my emacs config.
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.
In Mac OSX, I use homebrew with homebrew-emacs-head, I always install latest version of emacs via following command:
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
Gentoo Linux is the best linux distrobution I ever used and it’s really easy to install latest apps.
USE="X gtk3 inotify xft imagemagick" emerge app-editors/emacs
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 scripts/build-emacs.sh script to build latested emacs.
./scripts/build-emacs.sh
Note that if your are building under Mac OSX
, don’t forget to install xcode tools:
xcode-select --install
- First use git to download whole repo
git clone https://github.com/coldnew/coldnew-emacs.git
- Then use git submodule to download the spacemacs
git submodule update --init --recursive
- To generate the
init.el
, jut typemake
- If you do not put this repo on
~/.emacs.d
, you need to use following command to start emacsemacs -q -l ~/coldnew-emacs/init.el
Some extra packages need to be installed in the system manually. These packages are optional
but can make this configuration work more nicely.
In Mac OSX, I use homebrew to install opensource packages.
#brew install fasd
#brew install aspell --with-lang-en
<<install-in-macosx>>
In Gentoo Linux, don’t forget to enable USE=emacs
to make Gentoo auto install emacs-related packages.
#emerge app-shells/fasd
#emerge app-shells/aspell
<<install-in-gentoo>>
Some package like npm
use the same rule to install in any platform, here list what I need to install.
<<install-in-all>>
Since Emacs 27, we can add some setup in ~/.emacs.d/early-init.el
, these setup will be loadded before emacs startup.
;; early-init.el --- -*- lexical-binding: t; -*-
<<early-init>>
(provide 'early-init)
;;; early-init.el ends here
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.
(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$\\)")))
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.
(with-eval-after-load 'comp
(setq native-comp-async-report-warnings-errors 'silent))
(setq gc-cons-threshold most-positive-fixnum)
(push '(menu-bar-lines . 0) default-frame-alist)
(push '(tool-bar-lines . 0) default-frame-alist)
(push '(vertical-scroll-bars) default-frame-alist)
We plain to handle our package initialization in our configs, we must prevent Emacs from doing it at early stage.
(setq package-enable-at-startup nil)
(when (>= emacs-major-version 27)
(setq-default package-quickstart t))
(setq frame-inhibit-implied-resize t)
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.
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.
;; -*- lexical-binding: t -*-
Emacs 26 introduce new switch
bytecode which not contains in emacs-25, disable it so I can test both emacs-25 and emacs-26.
(setq byte-compile-cond-use-jump-table nil)
Some of my function may need the Common Lisp Extension, let’s import libraries first.
(require 'cl-lib) ; built-in
Add some extry buildin library I will use in my config file.
(require 'find-lisp)
Since emacs 24.4, new option load-prefer-newer
has been introduce, which make me never accidentally using outdated compiled files.
(setq load-prefer-newer t)
In this configuration, user-emacs-directory
always refer to the emacs
configuration’s init.el parent directory.
;; 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.")
Setup the cache directory to store some cache content.
(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)
Setup the modules directory to store some submodules and extra packages.
(defconst user-modules-directory
(file-name-as-directory (concat user-emacs-directory "modules"))
"My emacs storage area for modules.")
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.
(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.")
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.
(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)))))))
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.
(when (eq system-type 'darwin)
(setq-default mac-option-modifier 'super)
(setq-default mac-command-modifier 'meta))
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.
(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))
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.
;; 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)))
Only start server mode if I’m not root
(unless (string-equal "root" (getenv "USER"))
(require 'server)
(when (fboundp 'server-running-p)
(unless (server-running-p) (server-start))))
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.
(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)))
Also setup some backup settings.
(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)
Some emacs feature is not really useful
(setq ring-bell-function #'ignore)
Leave me a clean **scratch** buffer and I’ll be more happy :)
(setq initial-scratch-message "")
(setq visible-bell t)
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.
(defalias 'yes-or-no-p 'y-or-n-p)
(modify-all-frames-parameters '((fullscreen . maximized)))
It’s useful to have some basic personal information.
(setq user-full-name "Yen-Chin, Lee")
(setq user-mail-address "coldnew.tw@gmail.com")
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.
(defun my-load-secret ()
"Load my secret setting include password... etc."
(let ((secret "~/.secret.el.gpg"))
(when (file-exists-p secret) (load-file secret))))
The main package manager I use is emacs’s package.el
, it’s really nice and easy to use.
melpa contains many community packages that not contribute to emacs’s elpa, we add it here.
(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/"))))
Before we start to use package.el
, we need to initialize it first.
;; 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)))
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.
(eval-and-compile
(unless (package-installed-p 'use-package)
(package-refresh-contents)
(package-install 'use-package))) ; Installed by packages.el
use-package now can only need once, just add it to compile time
(eval-when-compile (require 'use-package))
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.
;; make `use-package' auto install non-installed packages.
(when (require 'use-package-ensure)
(setq use-package-always-ensure t))
Report details about loading and configuration.
(setq use-package-verbose t)
straight.el is next-generation, purely functional package manager for the Emacs hacker. It can integrated with use-package and install some packages from fork.
GitHub: https://github.com/raxod502/straight.el
(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://github.com/radian-software/straight.el/develop/install.el"
'silent 'inhibit-cookies)
(goto-char (point-max))
(eval-print-last-sexp)))
(load bootstrap-file nil 'nomessage))
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
(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))
Some common libraries I’ll use in my personal’s command or anything else.
(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)
Add UTF8 at the front of the priority list for automatic detection.
(prefer-coding-system 'utf-8)
Set up multilingual environment to use UTF-8.
(set-language-environment "UTF-8")
Set default value of various coding systems to UTF-8.
(set-default-coding-systems 'utf-8)
Use C
as locale for display time info (Actually it will display English).
(setq system-time-locale "C")
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.
(eval-after-load 'bookmark
'(progn
(setq abbrev-file-name
(concat user-cache-directory "abbrev_defs"))))
Move eshell cache dir to ~/.emacs.d/.cache/eshell
(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)))
(eval-after-load 'bookmark
'(progn
(setq-default bookmark-default-file
(concat user-cache-directory "bookmarks"))))
Major mode for editing IDL source files.
(eval-after-load 'idlwave
'(progn
(setq-default idlwave-config-directory
(concat user-cache-directory "idlwave"))))
;; change srecode cache file path
(eval-after-load 'srecode
'(progn
(setq-default srecode-map-save-file
(concat user-cache-directory "srecode-map.el"))))
(eval-after-load 'request
'(progn
(setq-default request-storage-directory
(concat user-cache-directory "request"))))
(eval-after-load 'nsm
'(progn
(setq-default nsm-settings-file
(concat user-cache-directory "network-security.data"))))
(eval-after-load 'url
'(progn
(setq url-configuration-directory
(file-name-as-directory
(concat user-cache-directory "url")))))
;; 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-")))))
Most of emacs packages do not need many configs or just provide commands/functions to use, I put them here.
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
(use-package discover-my-major
:defer 2 ; Install pkg if not exist after 2 sec idle time
:commands (discover-my-major))
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.
doxymacs is emacs’s wrapper for Doxygen.
(when (require 'doxymacs nil 'noerror)
(add-hook 'prog-mode-hook #'(lambda () (doxymacs-mode))))
To use doxymacs we also need to install it in system manually.
For Mac OSX, just type
brew install doxymacs
If you use Gentoo Linux, you can use following command to install this package
emerge app-shells/doxymacs
Benchmark Emacs Startup time without ever leaving your Emacs.
GitHub: https://github.com/jschaf/esup
(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))
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
(use-package exec-path-from-shell
:ensure t
:config
(when (memq window-system '(mac ns x))
(exec-path-from-shell-initialize)))
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
(use-package expand-region
:ensure t
:bind (("M-v" . er/expand-region)))
Emacs package to immitate narrow-to-region with more eye-candy.
GitHub: https://github.com/Malabarba/fancy-narrow
(use-package fancy-narrow :ensure t)
Focus provides focus-mode
that dims the text of surrounding sections, similar to iA Writer’s Focus Mode.
GitHub: https://github.com/larstvei/Focus
(use-package focus :ensure t)
Emacs fontawesome utility.
GitHub: https://github.com/syohex/emacs-fontawesome
(use-package fontawesome :ensure t)
This package allows to translate the strings using Google Translate service directly from GNU Emacs.
GitHub: https://github.com/atykhonov/google-translate
(use-package google-translate :ensure t)
Move point through buffer-undo-list positions.
GitHub: https://github.com/camdez/goto-last-change.el
(use-package goto-last-change
:ensure t)
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
(use-package howdoi
:defer 2
:commands (howdoi-query howdoi-query-line-at-point))
hungry-delete borrows hungry deletion from cc-mode
, which will causes deletion
to delete all whitespace in the direction you are deleting.
(use-package hungry-delete
:ensure t
:config
(global-hungry-delete-mode))
iedit let you edit multiple regions in the same way simultaneously.
GitHub: https://github.com/victorhge/iedit
(use-package iedit
:ensure t
:bind (("C-;" . iedit-mode)))
manage-minor-mode let you manage your minor-mode on the dedicated interface buffer.
(use-package manage-minor-mode :ensure t)
This Emacs package provides commands for moving to the beginning/end of code or line.
GitHub: https://github.com/alezost/mwim.el
(use-package mwim
:ensure t
:bind
(("C-a" . mwim-beginning-of-code-or-line)
("C-e" . mwim-end-of-code-or-line)))
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
(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))))
password-generator provides simple functions to create passwords and insert them inside buffer immediately.
GitHub: https://github.com/zargener/emacs-password-genarator
(use-package password-generator :ensure t)
rainbow-mode s a minor mode for Emacs which displays strings representing colors with the color they represent as background.
(use-package rainbow-mode :ensure t)
Smartparens is a minor mode for dealing with pairs in Emacs.
GitHub: https://github.com/Fuco1/smartparens
(use-package smartparens
:ensure t
:commands (smartparens-mode)
:config
(smartparens-mode 1))
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.
(use-package sx :ensure t)
tldr is a collection of simplified and community-driven man pages.
GitHub: https://github.com/kuanyui/tldr.el
(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")))
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
(use-package url-shortener :ensure t)
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
(use-package verify-url
:defer 2
:commands (verify-url))
visual-regexp for Emacs is like replace-regexp, but with live visual feedback directly in the buffer. Check out 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
(use-package visual-regexp :ensure t)
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
(use-package webpaste
:ensure t)
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 gude-key-mode, but the feature sets have diverged to a certain extent.
GitHub: https://github.com/justbur/emacs-which-key
(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))))
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.
Sometimes I just want to kill all buffers, this command will kill all
of them and make *scratch*
buffer alone.
(defun my/nuke-all-buffers ()
"Kill all buffers, leaving *scratch* only."
(interactive)
(mapcar (lambda (x) (kill-buffer x)) (buffer-list))
(delete-other-windows))
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.
(defun my/save-buffer-always ()
"Save the buffer even if it is not modified."
(interactive)
(set-buffer-modified-p t)
(save-buffer))
(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)))
(defun my/untabify-buffer ()
(interactive)
(save-excursion
(untabify (point-min) (point-max))))
(defun my/indent-whole-buffer ()
"Indent whole buffer."
(interactive)
(save-excursion
(indent-region (point-min) (point-max))))
(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))))
(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)))))
(defun my/quick-folding-source ()
"Use emacs buildin easy to folding code."
(interactive)
(set-selective-display
(if selective-display nil 1)))
Some of my partner’s file are in DOS format, so I need command to convert buffer between dos format and unix format.
(defun my/dos2unix ()
"Convert buffer file from dos file to unix file."
(interactive)
(set-buffer-file-coding-system 'undecided-unix 't) )
(defun my/unix2dos ()
"Convert buffer file from unix file to dos file."
(interactive)
(set-buffer-file-coding-system 'undecided-dos 't))
<U200B>
character is a zero width space character
which is nice to
use under org-mode.
For more info, please see: suggestion for org-emphasis-regexp-components: *U*nited *N*ations
(defun my/insert-U200B-char ()
"Insert <U200B> char, this character is nice use in org-mode."
(interactive)
(insert "\ufeff"))
(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))
(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."))
(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))))
(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)))
(defun my/copy-and-comment ()
"Copy region and comment it."
(interactive)
(kill-ring-save (region-beginning) (region-end))
(comment-dwim nil))
(defun my/file-reopen-as-root ()
(interactive)
(when buffer-file-name
(find-alternate-file
(concat "/sudo:root@localhost:"
buffer-file-name))))
(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)))))
(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)))))))
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.
(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"))))
(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))
(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))
A really nice command help me to find error on elisp buffer.
(defun my/eval-buffer-until-error ()
"Evaluate emacs buffer until error occured."
(interactive)
(goto-char (point-min))
(while t (eval (read (current-buffer)))))
(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))))
(defun my/reload-init ()
"Reload init.el file"
(interactive)
(load-file user-init-file))
If other window does not exist, split it, else switch to it.
(defun my/other-window-or-split ()
"Switch to other window or split it."
(interactive)
(when (one-window-p)
(split-window-horizontally))
(other-window 1))
If I have two windows at left/right position, this command can help me change left-window to right-window.
(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)))
My own emacs, my own style :)
Some emacs’s default UI feature setup.
The menu bar is one of the UI elements which work best with mouses.
(when (featurep 'menu-bar) (menu-bar-mode -1))
I never use the tool bar, it’s really no need.
(when (featurep 'tool-bar) (tool-bar-mode -1))
I hate the blinking cursor actually, it’s really annoying.
(blink-cursor-mode -1)
Actually when you familier with emacs, you don’t need to use scroll-bar anymore.
(when (featurep 'scroll-bar) (scroll-bar-mode -1))
I don’t want to enter the startup screen after initialize emacs.
(setq inhibit-startup-screen t)
Before use emacs’s load-theme
function, I advise it to make it fully unload previous theme before loading a new one.
;; 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))
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.
- styles/coldnew-theme.el
Basic utils and macros to define coldnew-theme.
- styles/day-coldnew-theme.el
My day theme.
- styles/night-coldnew-theme.el
My night theme.
(require 'day-coldnew-theme)
(require 'night-coldnew-theme)
(load-theme 'night-coldnew t nil) ; default use `night-coldnew-theme'
(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))
;; (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 "<fc=%s><%s></fc>"
;; (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)
(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))
(bind-keys :map global-map
("C-=" . my/increase-emacs-font-size)
("C--" . my/decrease-emacs-font-size))
(when (require 'minibuffer) ; buildin
<<minibuffer-config>>)
;; only use `bar' type of cursor shape
(add-hook 'minibuffer-setup-hook #'(lambda () (setq cursor-type 'bar)))
;; 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:"))
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’.
(use-package savehist
:config
(setq savehist-file (concat user-cache-directory "savehist.dat"))
(savehist-mode 1))
(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))
Though I am really familier with emacs, I still like some vim command.
(use-package evil
:ensure t
:config
;; enable evil-mode globally
(evil-mode t)
;; some configs setup later
<<evil-config>>
;; extra keybindings defined in `Keybinding' section
<<evil-keybindings>>
<<evil-ex-commands>>)
;; default state set to insert-state
(setq evil-default-state 'insert)
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
(setcdr evil-insert-state-map nil)
(define-key evil-insert-state-map
(read-kbd-macro evil-toggle-key) 'evil-emacs-state)
Make sure ESC
key in insert-state will call evil-normal-state
.
(define-key evil-insert-state-map [escape] 'evil-normal-state)
We also need to make all emacs-state buffer become to insert-state.
(dolist (m evil-emacs-state-modes)
(add-to-list 'evil-insert-state-modes m))
Evil Leader provides the <leader>
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
(use-package evil-leader
:ensure t
:after evil
:config
;; enable evil-leader globally
(global-evil-leader-mode)
;; extra keybindings defined in `Keybinding' section
<<evil-leader-keybindings>> )
This package emulates surround.vim by Tim Pope. The functionality is wrapped into a minor mode.
GitHub: https://github.com/timcharper/evil-surround
(use-package evil-surround
:ensure t
:after evil
:config
(global-evil-surround-mode 1))
This package emulates 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
(use-package evil-quickscope
:ensure t
:after evil
:config
(add-hook 'prog-mode-hook 'turn-on-evil-quickscope-always-mode))
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
(use-package evil-terminal-cursor-changer
:ensure t
:after evil
:commands (evil-terminal-cursor-changer-activate)
:config (evil-terminal-cursor-changer-activate))
GitHub: https://github.com/syohex/vi-tilde-fringe
(use-package vi-tilde-fringe
:ensure t
:if window-system
:config
(global-vi-tilde-fringe-mode))
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
(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))
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.
(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)
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:
(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
I don’t want emacs create some temporary file like .#-emacs-a08196
, disable it.
;; https://www.emacswiki.org/emacs/LockFiles
(when (version<= "24.3" emacs-version)
(setq create-lockfiles nil))
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.
GitHub: https://github.com/editorconfig/editorconfig-emacs
(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))
To use editorconfig we also need to install it in system manually.
For Mac OSX, just type
brew install editorconfig
If you use Gentoo Linux, you can use following command to install this package
emerge app-text/editorconfig-core-c
(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)
For Mac OSX, just type
brew install gpg
Most Linux already shipped with gnupg, if you use Gentoo Linux, you can use following command to install it
emerge app-crypt/gnupg
In my system, I always use gpg2
instead of gpg1
.
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
allow-emacs-pinentry
allow-loopback-pinentry
# (optional) setup timeout
pinentry-timeout 3
Then tell gpg-agent to load this configuration with gpgconf
in a shell:
gpgconf --reload gpg-agent
In your emacs, put this epa setup:
(require 'epa) ; built-in
(setq epg-pinentry-mode 'loopback)
All things done, let’s start the pinentry server
:
(use-package pinentry
:ensure t
:config
;; Start the Pinentry service
(pinentry-start))
(use-package tramp
:ensure t
:init
(setq tramp-persistency-file-name (concat user-cache-directory "tramp"))
:config
(setq tramp-default-method "rsync"))
In most case, I’ll make line numers display globally by linum
.
(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)))
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.
;; 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))))
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.
(use-package rainbow-delimiters
:ensure t
:config
(add-hook 'prog-mode-hook 'rainbow-delimiters-mode))
(use-package recentf
:straight (:type built-in)
:init (setq recentf-save-file (expand-file-name "recentf" user-cache-directory))
:config
(recentf-mode 1))
highlight-numbers
is an Emacs minor mode that highlights numeric literals in
source code.
GitHub: https://github.com/Fanael/highlight-numbers
(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)))))
GitHub: https://github.com/dgutov/highlight-escape-sequences
(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))
(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)
GitHub: https://github.com/zk-phi/indent-guide
(use-package indent-guide
:ensure t
:config
;; Only show indent-guide in idle-time.
(setq indent-guide-delay 0.1))
(show-paren-mode 1)
(setq show-paren-delay 0) ; no delay
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
(use-package dtrt-indent
:ensure t
:config
;; enable dtrt-indent-mode globally
(dtrt-indent-mode 1))
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
(use-package whitespace-cleanup-mode
:ensure t
:config
(add-hook 'prog-mode-hook 'whitespace-cleanup-mode))
Want to edit Firefox’s textarea in emacs ?
First, you need to install Edit with Emacs on Firefox.
Then, in emacs, add following code to install
(use-package edit-server
:ensure t
:config
(edit-server-start))
(setq tab-always-indent 'complete)
(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) ;; ハイライトキャンセル
)
ref: https://www.reddit.com/r/emacs/comments/8sw3r0/finally_scrolling_over_large_images_with_pixel/
(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.
Standard Emacs undo is kind of confusing. 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
(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))
Sometimes I’ll clean the *scratch*
buffer by kill it, add following function
to let emacs re-create it automatically.
;; Create *scratch* automatically
(run-with-idle-timer 1 t
#'(lambda ()
(unless (get-buffer "*scratch*")
(with-current-buffer (get-buffer-create "*scratch*")
(lisp-interaction-mode)))))
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>
).
(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 "^\\*"))
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: EmacsWiki: Registers
(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)))
(bind-keys :map my-editor-map
;("C-x n" . bm-next)
;("C-x p" . bm-previous)
;("C-x ." . bm-toggle)
)
(use-package helm
:straight t
:init
<<helm-init>>
:config
<<helm-config>>)
Since helm integrate some external tool like gtags, cscope …etc. We need to install these tools to our system.
It’s recommand to use homebrew to install the_silver_searcher under Mac OSX.
brew install global
brew install cscope
If you use Gentoo Linux, you can use portage to install it.
emerge dev-util/cscope
emerge dev-util/global
Enable helm mode by default.
(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)
;; Use fuzzy match in helm
(setq helm-M-x-fuzzy-match t)
(setq helm-buffers-fuzzy-matching t)
(setq helm-recentf-fuzzy-match t)
;; 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)
GitHub: https://github.com/yasuyk/helm-bm
(use-package helm-bm :ensure t :after (helm))
This package uses 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
(use-package helm-dash :ensure t :after (helm))
helm-gtags.el
is GNU GLOBAL helm interface.
GitHub: https://github.com/syohex/emacs-helm-gtags
(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))
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
(use-package helm-swoop :ensure t :after (helm))
GitHub: https://github.com/emacs-jp/helm-c-yasnippet
(use-package helm-c-yasnippet
:ensure t
:after (helm yasnippet)
:config
(setq helm-yas-space-match-any-greedy t))
(use-package helm-smex :ensure t :after (helm))
(bind-keys :map helm-map
("TAB" . helm-execute-persistent-action)
("<tab>" . 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))
(use-package org
:ensure nil ; built-in
:mode (("\\.org\\'" . org-mode)
("\\.org_archive\\'" . org-mode))
:config
(setq org-url-hexify-p nil)
<<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)
Always enable auto indent for org-mode.
(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))))
Show org-mode bullets as UTF-8 characters.
GitHub: https://github.com/sabof/org-bullets
(use-package org-bullets
:ensure t
:after (org)
:config
(add-hook 'org-mode-hook #'(lambda () (org-bullets-mode 1))))
(setq org-todo-keywords '((sequence "TODO(t)" "|" "DONE(d)")
(sequence "WAITING(w)" "|")
(sequence "|" "CANCELED(c)")))
Call visual-line-mode
to have soft-wrap.
(add-hook 'org-mode-hook #'visual-line-mode)
(add-hook 'org-mode-hook #'(lambda () (electric-pair-local-mode -1)))
org-mode make it easy to insert blocks by typing <s[TAB]
…etc. I
defined some extra easy-templates I need to use here.
;; NOTE:
;; After org-mode 9.2, we need to require `org-tempo' module
;; to make easy-template work
(when (not (version< (org-version) "9.2"))
(require 'org-tempo))
(add-to-list 'org-structure-template-alist
'("el" . "src emacs-lisp"))
(add-to-list 'org-structure-template-alist
'("S" . "src sh"))
(add-to-list 'org-structure-template-alist
'("p" . "src plantuml :file uml.png"))
(org-babel-do-load-languages
'org-babel-load-languages
'((emacs-lisp . t)
(C . t)
(ditaa . t)
(dot . t)
(js . t)
(latex . t)
(perl . t)
(python . t)
(ruby . t)
;; (sh . t)
(shell . t)
(plantuml . t)
(R . t)
(clojure . t)))
;; make dot work as graphviz-dot
(add-to-list 'org-src-lang-modes '("dot" . graphviz-dot))
An abbreviated link looks like
[[linkword:tag][description]]
(setq org-link-abbrev-alist
'(("google" . "http://www.google.com/search?q=") ; ex: [[google:hi emacs]]
("google-map" . "http://maps.google.com/maps?q=%s") ; ex: [[google-map:taiwan]]
("wiki" . "https://en.wikipedia.org/wiki/%s") ; ex: [[wiki:emacs]]
))
;; make agenda show on current window
(setq org-agenda-window-setup 'current-window)
;; highlight current in agenda
(add-hook 'org-agenda-mode-hook 'hl-line-mode)
;; Setup files for agenda
(setq org-directory "~/Org/tasks")
;; U all .org files in `org-directory'
(setq org-agenda-files
(find-lisp-find-files org-directory "\.org$"))
;;
(setq org-default-notes-file (f-join org-directory "tasks" "TODO.org"))
;; Always use `C-g' to exit agenda
(add-hook 'org-agenda-mode-hook
#'(lambda ()
(local-set-key (kbd "C-g") 'org-agenda-exit)))
;; Use speed command to quick navigating
(setq org-use-speed-commands t)
;; Log timestamp when done
(setq org-log-done 'time)
(setq org-capture-templates
'(("t" "TODO" entry (file+headline "" "Tasks") "* TODO %?\n %i\n")
("n" "NOTE" entry (file+headline "" "Tasks") "* NOTE %?\n %i\n %a")
("l" "Links" entry (file+headline "" "Links") "* TODO %? :link:\nSCHEDULED: <%<%Y-%m-%d %a>>\n %i\n %a")
("j" "Journal" entry (file+datetree "" "Journal") "* %?\nEntered on %U\n %i\n %a")
))
(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)))
see: http://emacs.stackexchange.com/questions/450/intelligent-spell-checking-in-org-mode
(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"))
))
(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))
org-download will let you drag-and-drop image to your org-mode file easily.
GitHub: https://github.com/abo-abo/org-download
(use-package org-download
:ensure t
:config
;; add support to dired
(add-hook 'dired-mode-hook 'org-download-enable))
(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))
(bind-keys :map org-src-mode-map
("C-c C-c" . org-edit-src-exit))
GitHub: https://github.com/skuro/plantuml-mode
(use-package plantuml-mode
:ensure t
:mode ("\\.plantuml\\'")
:init
;; FIXME: setup plantuml jar path
;; FIXME: add org-mode support
)
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.
(use-package bison-mode
:ensure t
:mode ("\\.y\\'" "\\.l\\'" "\\.jison\\'"))
GN is a meta-build system that generates NinjaBuild files. This system is widely used on Google’s chromium related framework.
Take a look on GN reference or GN Quick Start Guide for more info.
(use-package gn-mode
:ensure t
:mode ("BUILD.gn" "\\.gni?\\'"))
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 markdown-mode to help me integrate markdown with emacs, the README.md is bind to gfm-mode
for github’s markdown flavor.
(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
<<markdown-config>>)
Syntax highlighting for code blocks in Emacs Markdown Mode give us some hint to use mmm-mode
syntax highlight code block on markdown-mode.
;; 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")))
(bind-keys :map markdown-mode-map
("C-c i" . markdown-insert-link))
(bind-keys :map gfm-mode-map
("C-c i" . markdown-insert-link))
(use-package nasm-mode :ensure t)
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.
(use-package toml-mode
:ensure t
:mode "\\.toml$")
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.
(use-package yaml-mode
:ensure t
:mode "\\.yml$")
(use-package ess
:ensure t
:mode ("\\.[rR]\\'" . R-mode)
:config
<<R-config>>)
(use-package qml-mode
:ensure t
:mode "\\.qml$"
:config
<<qml-config>>)
(use-package indent-guide
:ensure t
:config
(add-hook 'qml-mode-hook #'indent-guide-mode))
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: Vala Tutorial
(use-package vala-mode
:ensure t
:mode ("\\.vala\\'" "\\.vapi\\'")
:config
<<vala-config>>)
(use-package verilog-mode
:mode ("\\.v\\'")
:config
<<verilog-config>>)
(setq verilog-linter "verilator --lint-only")
;; https://github.com/flycheck/flycheck/issues/1250
(setq flycheck-verilog-verilator-executable "/usr/bin/verilator_bin")
(use-package groovy-mode
:mode (("\\.groovy" . groovy-mode)
("/Jenkinsfile" . groovy-mode))
:ensure t)
(use-package svelte-mode
:ensure t
:mode ("\\.svelte\\'" . svelte-mode))
Since emacs not built-in all configration files syntax highlight support, we need to install manually.
(use-package dockerfile-mode
:ensure t
:mode "Dockerfile\\'")
(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)))
(use-package systemd
:ensure t)
(use-package cmake-mode
:ensure t
:mode (("CMakeLists\\.txt\\'" . cmake-mode) ("\\.cmake\\'" . cmake-mode)))
;; 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))
(use-package meson-mode
:ensure t
:mode (("meson\\.build\\'" . meson-mode)))
(use-package cc-mode
:mode
(("\\.h\\'" . c++-mode)
("\\.c\\'" . c-mode)
("\\.hpp\\'" . c++-mode)
("\\.cpp\\'" . c++-mode)
("\\.cc\\'" . c++-mode))
:config
<<cc-mode-config>>)
(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))))
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) {
)
(use-package cwarn
:config
(add-hook 'c-mode-common-hook #'(lambda () (cwarn-mode 1))))
(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)
In most C/C++ project, we naming variable in camelCase, subword-mode
can help us treat helloWorld
as two words.
;; subword-mode, e.g., someThing is treated as two words
(add-hook 'c-mode-common-hook #'(lambda () (subword-mode 1)))
(add-hook 'c-mode-common-hook 'electric-pair-mode)
Semantic Refactor is a C/C++ refactoring tool based on Semantic parser framework.
GitHub: https://github.com/tuhdo/semantic-refactor
(use-package srefactor
:ensure t
:defer t
:after (cc-mode))
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
(use-package cff
:ensure t
:after (cc-mode))
Some syntax highlight may not support in default emacs, set it here.
Extra hightlight for stdint.h
(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))))
;; 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))
Since C/C++ has too many coding styles, I need to set it up.
I always use linux coding style
for c language by default.
(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)))
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.
(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 <linux/\\(module\\|kernel\\)\\.h>$" 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)
Use my C++ coding style.
(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)
))
(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)))))
;; clang-format: format C/C++ buffers using clang-format
;; https://github.com/emacsorphanage/clang-format
(use-package clang-format
:ensure t)
(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))
Though LISP
has many dialet, it still is the best programming language I ever met.
(use-package elisp-mode
:ensure nil ; built-in
:config
<<emacs-lisp-mode-config>>)
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
(use-package macrostep
:ensure t)
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
(use-package el-spice
:ensure t)
(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))))))
(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)))
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
(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))
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
(use-package page-break-lines
:ensure t
:config
;; enable globally
(global-page-break-lines-mode 1))
(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)
(bind-keys :map emacs-lisp-mode-map
;; ("C-c '" . my/narrow-or-widen-dwim)
)
I now use Hexo with my fork of hexo-renderer-org for blogging, hexo.el is a nice plugin to control hexo blog post in Emacs.
However, I use my fork of hexo.el since threre’s some feature I want to but not exist in upstream.
;; 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")))
(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/"))
)
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.
(setq vc-handled-backends nil)
Magit is an interface to the version control system Git, implemented as an Emacs package. Magit aspires to be a complete Git porcelain. While we cannot (yet) claim that Magit wraps and improves upon each and every Git command, it is complete enough to allow even experienced Git users to perform almost all of their daily version control tasks directly from within Emacs. While many fine Git clients exist, only Magit and Git itself deserve to be called porcelains.
GitHub: https://github.com/magit/magit
(use-package magit
:ensure t
:config
<<magit-config>>)
I always add sign-off
to the commit and make magit verbose.
(setq magit-commit-arguments '("--verbose" "--signoff"))
If you use git in command line, you can turn on diff-highlight by following command
git config --global core.pager "diff-highlight | less --tabs=4 -RFX"
With magit, we can use M-x magit-toggle-diff-refine-hunk
or make it enable by default:
(setq magit-diff-refine-hunk 'all)
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
(use-package git-modes :ensure t)
GitHub: https://github.com/syohex/emacs-git-gutter-fringe
(use-package git-gutter-fringe
:ensure t
:if window-system ; git-gutter-fringe only work on GUI
:config
;; enable globally
(git-gutter-mode))
emacs has some IDE feature, add here.
(use-package flycheck
:ensure t
:config
;; enable globally
(global-flycheck-mode))
https://archive.casouri.cc/note/2023/tree-sitter-starter-guide/index.html
(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)))
(use-package yasnippet
:ensure t
:mode ("emacs.+/snippets/" . snippet-mode)
:config
;; enable yasnippet globally
(yas-global-mode 1)
;; extra yasnipet configs
<<yasnippet-config>>)
(setq yas-prompt-functions '(yas-dropdown-prompt
yas-completing-prompt
yas-ido-prompt))
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.
(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)))
(add-hook 'term-mode-hook (lambda() (yas-minor-mode -1)))
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.
(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 \"<e\" on an otherwise empty line and
expands them.
Before use this function, you must setup `major-mode-name'-expand-alist variable.
Take emacs-lisp-mode as example, if you wand to use <r to expand your snippet `require'
in yasnippet, you muse setup the emacs-lisp-mode-expand-alist variable.
(setq emacs-lisp-expand-alist '((\"r\" . \"require\")))"
(let* ((l (buffer-substring (pos-bol) (point)))
(expand-symbol (intern (concat (symbol-name major-mode) "-expand-alist")))
(expand-alist (if (boundp expand-symbol) (symbol-value expand-symbol) nil))
a)
(when (and (looking-at "[ \t]*$")
(string-match "^[ \t]*<\\([a-zA-Z]+\\)$" l)
(setq a (assoc (match-string 1 l) expand-alist)))
(delete-char (1+ (length (car-safe a))))
(if (symbolp (cdr-safe a))
(funcall (cdr-safe a))
(insert (cdr-safe a)))
t)
ad-do-it))
Take emacs-lisp-mode as example, if I want to use <r
and press TAB
then yasnippet will expand the command, just add following code:
(setq emacs-lisp-mode-expand-alist '(("r" . "require")))
For c-mode, just do the same but change the relative major-mode-expand-alist like following
(setq c-mode-expand-alist '(("i" . "include")))
(use-package flymake-shell
:ensure t
:config (add-hook 'sh-set-shell-hook 'flymake-shell-load))
(use-package bitbake
:ensure t
:mode ("\\.bb\\'" "\\.bbappend\\'"))
(use-package dts-mode :ensure t
:mode ("\\.dts\\'" "\\.dtsi\\'"))
(use-package dart-mode
:ensure t
:mode ("\\.dart\\'")
:config
;; enable analyzer support
(setq dart-enable-analysis-server t)
;; add flycheck support
(add-hook 'dart-mode-hook 'flycheck-mode))
A major mode for Emacs for interacting with Gnuplot
GitHub: https://github.com/bruceravel/gnuplot-mode
(use-package gnuplot :ensure t
:commands gnuplot-mode
:mode "\\.gp$")
(use-package graphviz-dot-mode :ensure t
:mode "\\.dot\\'"
:config
;; alias `dot-mode' to graphviz-dot-mode
(defalias 'dot-mode 'graphviz-dot-mode))
(use-package glsl-mode :ensure t
:mode (("\\.vs\\'" . glsl-mode)
("\\.fs\\'" . glsl-mode)
("\\.gs\\'" . glsl-mode))
:config
(setq glsl-other-file-alist '(("\\.fs$" (".vs")) ("\\.vs$" (".fs")))))
(use-package js2-mode
:ensure t
:mode "\\.js\\'")
(use-package js2-refactor
:ensure t)
(use-package nvm :ensure t)
To make emacs work with javascript more nicer, we need to install some packages in system.
tern
for auto-completion and documentation features:
npm install -g tern
We also install eslint
with babel and react support, to use eslint
you need to add .eslintrc
to your project, here’s a good example: .eslintrc .
npm install -g eslint babel-eslint eslint-plugin-react
npm install -g jsxhint
ref: http://umi-uyura.hatenablog.com/entry/2015/05/13/214629
Finally, install js-beautify
to do automatic code formatting:
npm install -g js-beautify
Be sure to have the e4x
option set to true on your .jsbeautifyrc
here it is my configuration as an example:
{
"indent_size": 2,
"indent_char": " ",
"eol": "\n",
"indent_level": 0,
"indent_with_tabs": false,
"preserve_newlines": true,
"max_preserve_newlines": 2,
"jslint_happy": false,
"space_after_anon_function": false,
"brace_style": "collapse",
"keep_array_indentation": false,
"keep_function_indentation": false,
"space_before_conditional": true,
"break_chained_methods": true,
"eval_code": false,
"unescape_strings": false,
"wrap_line_length": 80,
"wrap_attributes": "auto",
"wrap_attributes_indent_size": 2,
"e4x": true,
"end_with_newline": true
}
import-js
is a tool to automatically import dependencies in your JavaScript
project. Use it in Vim or Emacs by placing your cursor on a variable and hit
<leader>j (Vim)
, or (M-x) import-js-import (Emacs)
.
GitHub: https://github.com/trotzig/import-js
(use-package import-js :ensure t)
(use-package json-mode :ensure t
:mode "\\.json\\'")
(use-package json-reformat :ensure t :commands json-reformat-region)
(use-package flymake-json :ensure t
:config
(add-hook 'json-mode-hook (lambda () (flymake-json-load))))
(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))
)
(use-package python
:mode (("SCons\\(truct\\|cript\\)\\'" . python-mode)
("DEPS" . python-mode)))
(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"))
(use-package go-mode
:ensure t
:config
<<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))
(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)
(bind-keys :map go-mode-map
("M-." . godef-jump))
(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))
Though LISP
has many dialet, it still is the best programming
language I ever met.
Common setup for LISP development.
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/
(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))
(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))
Show lambda as λ.
(global-prettify-symbols-mode 1)
(use-package web-mode
:ensure t
:mode (("\\.html?\\'" . web-mode)
("\\.ejs?\\'" . web-mode)))
(use-package css-mode
:ensure nil ; built-in
:mode "\\.css\\'")
(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))
(use-package less-css-mode
:ensure t
:mode ("\\.less$" . less-css-mode))
(use-package scss-mode
:ensure t
:mode "\\.scss\\'"
:config
;; dont' build scss to css after save file
(setq scss-compile-at-save nil))
Sometimes we will use mustache as template system, mustache-mode is a nice helper.
GitHub: https://github.com/mustache/emacs
(use-package mustache-mode :mode "\\.mustache$" :ensure t)
emmet-mode is a fork of 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
(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 "<tab>") 'emmt-expand-yas)))
After the ansi-term process ends it should leaves a buffer.
(defadvice term-handle-exit (after kill-buffer-after-exit activate)
"Kill the term buffer if the process finished."
(kill-buffer (current-buffer)))
eshell is not really a system shell, it’s written in pure lisp. What I like is it fully integrated with emacs.
(use-package eshell
:config
;; extra eshell configs
<<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) " # " " $ "))))
;; 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)
(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")))
Eshell Autojump is an 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
(use-package eshell-autojump :ensure t)
(use-package esh-autosuggest
:hook (eshell-mode . esh-autosuggest-mode)
:ensure t)
(defun eshell/.. (&optional level)
"Go up LEVEL directories"
(interactive)
(let ((level (or level 1)))
(eshell/cd (make-string (1+ level) ?.))
(eshell/ls)))
(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))))
(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)
(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))))
;; 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)))
(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))
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
ranger, a file manager written in Python.
GitHub: https://github.com/wasamasa/eyebrowse
(use-package eyebrowse
:ensure t
:config
;; enable eyebrowse globally
(eyebrowse-mode t))
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:
(setq window-numbering-assign-func
(lambda () (when (equal (buffer-name) "*Calculator*") 9)))
GitHub: https://github.com/nschum/window-numbering.el
(use-package window-numbering
:ensure t)
(bind-keys :map global-map
("C-x C-s" . my/save-buffer-always))
(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)
(evil-define-key 'insert my-editor-map
(kbd "<delete>") '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-<SPC>") '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-<RET>") 'insert-empty-line
(kbd "s-<SPC>") 'insert-U200B-char
(kbd "C-x C-d") 'dired
;; (kbd "M-o") 'other-window
;; (kbd "TAB") 'yas/expand
)
For space
state, I use evil-leader to achive this goal.
(evil-leader/set-leader "<SPC>")
(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)
(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)
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.
(let ((secret "~/.personal.el"))
(when (file-exists-p secret) (load-file secret)))