No magic, no difficulty, just use Emacs.
Designed for an easy, humanized intuitive, out-of-the-box Emacs.
Emacs is not a fearful existence.
- Download the file: init.el and copy it to:
- Linux/Uinx User
~/.emacs.d/init.el
- Windows User
C:/Users/YourUserName/AppData/Roaming/.emacs.d/init.el
- Start Emacs and wait for a while, Emacs will automatically download the content.
If you encounter a prompt asking you to make a choice about network, select: always
Once Emacs has completed its setup, continue reading…
Emacs is primarily driven by using key-combinations. When we describe these key-combinations we use short forms, and these are reflected in both the way you configure key-bindings in emacs and the way emacs describes them to you:
| Keyboard | Emacs Key Name | Example | Comment |
|---|---|---|---|
| Ctrl | C- | C-x C-f | Press Ctrl and x together, and then Ctrl and f together |
| Alt | M- | M-x | Press Alt and x together. |
| Enter | RET | M-x emacs-version RET | Press Alt and x together, then type emacs-version and finally press Enter or Return. |
The following are some of the most important key-bindings you’ll need to know to control Emacs:
| Emacs Keybinding | Comment |
|---|---|
| C-h t | Start the Emacs tutorial |
| C-x C-f | Open File |
| C-x C-s | Save File |
| C-x C-c | Exit Emacs |
| M-x | Execute Emacs command |
| M-x emacs-version RET | Example Emacs command |
| C-@ | Select text |
| M-w | Copy text |
| C-w | Cut text |
| C-y | Paste text |
| M-y | Preview and cycle paste text (press repeatedly to cycle through items) |
| M-x list-packages RET | Open Emacs package management UI. |
You can move the cursor around using the arrow keys, as per any modern text editor.
Although, for many users, it isn’t necessary to customise Emacs, one of the things that makes Emacs unique is the nearly unlimited level of customisation that is possible using Emacs’ built in programming language, Emacs Lisp.
If you’re not comfortable working with a programming language, you can also make changes to settings, apply and save them, using Emacs customisation user interface. To access this feature type: M-x customize RET.
If you only care about the functions that need to be called manually by the user, then you jump directly to the title: recent
The init.el file you downloaded to setup OpenEmacs is an example of Emacs Lisp, and is the place where all further configuration should happen. Here are some examples of things that you can tweak easily:
;; -*- lexical-binding: t; -*-
(add-to-list 'default-frame-alist '(fullscreen . maximized)) ;; Maximize window after starting Emacs
(setq inhibit-startup-message t) ;; Close Emacs launch screen
(setq inhibit-splash-screen t) ;; Close Emacs startup help screen
(setq initial-scratch-message (concat ";; Happy hacking, " user-login-name " - Emacs \u2665 you!\n\n"))
;; Show your last execute command
(setq frame-title-format
'(:eval (format "Emacs - %s [ %s ]"
(buffer-name)
last-command))
icon-title-format t)
;; (menu-bar-mode 0) ;; Emacs Text Toolbar above
(tool-bar-mode 0) ;; Close Emacs icon toolbar above
(scroll-bar-mode 0) ;; Close scrollbar
(setq ring-bell-function 'ignore) ;; Close Emacs warning sound
;; File related: Backup, Delete Recycle Bin
(setq make-backup-files nil ;; Close the backup file
create-lockfiles nil ;; Close Create a backup file
delete-by-moving-to-trash t) ;; Emacs moves to the recycling bin when deleting filesNote that lines starting with ;; are commented out.
This example shows how to enable an Emacs theme. Note: themes are distributed as Emacs packages.
;; light
(load-theme 'modus-operandi-tinted)
;; dark
;; (load-theme 'modus-vivendi-tinted)This example shows how to adjust properties of fonts in use.
(set-face-attribute 'default nil :height 160)
;; (set-face-attribute 'default nil :family "Consolas" :height 140)This example shows how you can define sources for obtaining Emacs packages on-line.
(setq package-archives '(("gnu" . "https://elpa.gnu.org/packages/")
("nongnu" . "https://elpa.nongnu.org/nongnu/")
("melpa" . "https://melpa.org/packages/")))
;; Sometimes you want to keep the package available, so that it can be fixed in a certain version forever.
;; (setq package-archives '(("melpa" . "https://raw.githubusercontent.com/d12frosted/elpa-mirror/5a83cbae8df2c23a24b1509bfe808f6a89e5a645/melpa/");; 2025-07-20 8:00
;; ("gnu" . "https://raw.githubusercontent.com/d12frosted/elpa-mirror/5a83cbae8df2c23a24b1509bfe808f6a89e5a645/gnu/");; 2025-07-20 8:00
;; ("org" . "https://raw.githubusercontent.com/d12frosted/elpa-mirror/5a83cbae8df2c23a24b1509bfe808f6a89e5a645/org/");; 2025-07-20 8:00
;; ("nongnu" . "https://raw.githubusercontent.com/d12frosted/elpa-mirror/5a83cbae8df2c23a24b1509bfe808f6a89e5a645/nongnu/");; 2025-07-20 8:00
;; ))
;; There is another way, if you want to install a package from a certain git repo, you can use the :vc syntax.
;; (use-package eglot-booster
;; :ensure t
;; :vc (:url "https://github.com/jdtsmith/eglot-booster"
;; ;; Or :rev "tag-xxx"
;; :rev "e6daa6bcaf4aceee29c8a5a949b43eb1b89900ed"))Note: Users don’t need to care about how to use this, it is already in use.
vertico is a plugin that provides user-friendly for Emacs minibuffer.
(use-package vertico
:ensure t
:hook (after-init . vertico-mode)
:bind (:map vertico-map
("DEL" . vertico-directory-delete-char))
:custom
(vertico-count 10)
)Note: Users don’t need to care about how to use this, it is already in use.
orderless is a tool that provides fuzzy search and is very practical.
(use-package orderless
:ensure t
:config
(setq completion-styles '(orderless basic)
completion-category-defaults nil
completion-category-overrides '((file (styles partial-completion)))))Note: Users don’t need to care about how to use this, it is already in use.
marginalia allows Emacs minibuffer to display comments.
;; Display information in Minibuffer
(use-package marginalia
:ensure t
:hook (after-init . marginalia-mode))Let Emacs’ modeline display time
;; modeline display time
(use-package time
:ensure nil
:hook (after-init . display-time-mode)
:custom
(display-time-24hr-format t);; 24-hour system
(display-time-format "%m-%d %a %H:%M")
(display-time-day-and-date t) ;; Show time, day, date
)Note: Users don’t need to care about how to use this, it is already in use.
autorevert causes files to be automatically updated in Emacs when an external program makes a change to them.
;; Automatically update files after external changes
(use-package autorevert
:ensure nil
:hook (after-init . global-auto-revert-mode))Note: Users don’t need to care about how to use this, it is already in use.
saveplace will automatically restore your location in the file to where you were in the file last time to opened it.
;; Where the cursor is located before saving each file
(use-package saveplace
:ensure nil
:hook (after-init . save-place-mode)
:custom
(save-place-file "~/.emacs.d/places"))Note: Users don’t need to care about how to use this, it is already in use.
which-key can help the user indicate what functions your next key will perform.
(use-package which-key
:ensure nil
:if (>= emacs-major-version 30)
:diminish
:hook (window-setup . which-key-mode))Note: Users don’t need to care about how to use this, it is already in use.
Show the buffer names as a row of tabs at the top of the window.
(use-package tab-line
:ensure nil
:hook (window-setup . global-tab-line-mode))Note: Users don’t need to care about how to use this, it is already in use.
elec-pair is an Emacs tool for automatically pairing parentheses.
You might find it strange that even parentheses completion needs to be enabled; this is thanks to Emacs being fully customizable by users according to their personal preferences.
(use-package elec-pair
:ensure nil
:hook (after-init . electric-pair-mode))Note: Users don’t need to care about how to use this, it is already in use.
company is a complete framework for Emacs.
C-g to quit complete.
(use-package company
:ensure t
:hook (after-init . global-company-mode)
:custom
(company-idle-delay 0)
(company-minimum-prefix-length 2))recentf will automatically record the file you open, making it easier to open it next time.
To open a file from the list of recently opened files type M-x recentf RET
(use-package recentf
:ensure nil
:hook (after-init . recentf-mode)
:custom
(recentf-filename-handlers '(abbreviate-file-name))
(recentf-max-saved-items 400)
(recentf-max-menu-items 400)
(recentf-save-file "~/.emacs.d/recentf")
:config
(recentf-cleanup))Note: Users don’t need to care about how to use this, it is already in use.
undo-fu is an Emacs tool that persistently saves your editing history.
| Call | Key | Comment |
|---|---|---|
| M-x undo-fu-only-undo | C-/ | Undo |
| M-x undo-fu-only-redo | C-? | Redo |
(use-package undo-fu
:ensure t
:bind
(([remap undo-redo] . undo-fu-only-redo)
([remap undo] . undo-fu-only-undo))
:custom
(undo-limit 67108864) ; 64mb.
(undo-strong-limit 100663296) ; 96mb.
(undo-outer-limit 1006632960) ; 960mb.
)
(use-package undo-fu-session
:ensure t
:hook (after-init . undo-fu-session-global-mode)
:custom
(undo-fu-session-directory "~/.emacs.d/undo-fu-session")
(undo-fu-session-compression 'nil) ;; Default `Emacs builtin`, You Can use ==> BZip2/GZip/XZ/Z-Standrad
)project automatically detects the root-folder of project that uses source-control (e.g. git or subversion). Within such a project you can search for the entire project content with the following commands and key-bindings:
| Key | Func | Comment |
|---|---|---|
| C-x pf | project-find-file | Search Project File |
| C-x pd | project-find-dir | Search Project Directory |
| C-x pb | project-switch-to-buffer | Search Project buffer |
| C-x pg | project-find-regexp | Search Project text |
| C-x pr | project-query-replace-regexp | Project replace text |
| (It is recommended to use the next title: `deadgrep` instead of this) | (Maybe Windows system failed to use) | |
| C-x pc | project-compile | Run Project compile(e.g. make) |
| ...... | ...... | ...... |
(use-package project
:ensure nil)deadgrep is a tool for searching/replacing text with the help of ripgrep.
To use deadgrep, you must install: GitHub - BurntSushi/ripgrep: ripgrep recursively searches directories for a r…
| Key | Func | Comment |
|---|---|---|
| C-x pg | deadgrep | Search/Replace Text |
If you want to find and replace certain text in all files under the project, then you can:
- C-x pg Enter text to search (replace) and then Enter
- Use C-x C-q to switch read-only/write method, directly modify content, all files can be modified
- Then observe whether the file/buffer content of your project has changed
(use-package deadgrep
:ensure t
:bind
(([remap project-find-regexp] . deadgrep)))consult is a collection of various tool commands for Emacs.
consult provides preview/extension/visualization functions for these tool commands.
Discover consult is unique:
- First open two files/buffers
- Call: M-x switch-to-buffer RET and observe
- Call: M-x consult-buffer RET and you will find that consult comes with the preview
The following consult-xxxx is a common function, and you can explore it slowly. It doesn’t matter if you don’t care.
| Command | Comment |
|---|---|
| consult-line | Search the text of the current buffer |
| consult-recent-file | Search and open the recently opened file, similar to `M-x recentf` |
| consult-ripgrep | Use `ripgrep` to search for (item) text, similar to `deadgrep` |
| consult-imenu | Search for the symbol/function/title of the current file |
| ....... | ...... |
(use-package consult
:ensure t
:bind
(([remap imenu] . consult-imenu)
([remap switch-to-buffer] . consult-buffer)
([remap switch-to-buffer-other-window] . consult-buffer-other-window)
([remap switch-to-buffer-other-frame] . consult-buffer-other-frame)
("M-g M-g" . consult-line)
("M-g g" . consult-goto-line)
([remap bookmark-jump] . consult-bookmark)
([remap repeat-complex-command] . consult-complex-command)
([remap yank-pop] . consult-yank-pop)
([remap Info-search] . consult-info)
("C-c cf" . consult-recent-file)
("C-c cF" . consult-flymake)
("C-c cg" . consult-grep)
("C-c cG" . consult-line-multi)
("C-c ck" . consult-kmacro)
("C-c cl" . consult-locate)
("C-c co" . consult-outline)
("C-c cr" . consult-ripgrep)
:map isearch-mode-map
("C-c h" . consult-isearch-history)
:map minibuffer-local-map
("C-c h" . consult-history)
:map org-mode-map
([remap imenu] . consult-outline))
:custom
(register-preview-delay 0.5)
(register-preview-function #'consult-register-format)
(xref-search-program 'ripgrep)
(xref-show-xrefs-function #'consult-xref)
(xref-show-definitions-function #'consult-xref)
(consult-preview-key 'any) ;; Preview content, can be set to buttons
(consult-async-refresh-delay 1.0) ;; Prevent Emacs from being stuck by using external programs, for example: consult-ripgrep
(consult-async-min-input 2) ;; Start searching at the minimum number of characters
(consult-narrow-key "?") ;; Optional module buttons
:config
;; Support Windows system `everythine.exe` software search file to use `conslut-locate`
(when (and (eq system-type 'windows-nt))
(setq consult-locate-args (encode-coding-string "es.exe -i -p -r" 'gbk)))
;; Disable preview of certain features
(defmacro +no-consult-preview (&rest cmds)
`(consult-customize ,@cmds :preview-key "M-."))
(+no-consult-preview
consult-ripgrep consult-git-grep consult-grep
consult-bookmark consult-recent-file
consult--source-recent-file consult--source-project-recent-file consult--source-bookmark)
)Here we will introduce you to how to code in Emacs.
LSP is a protocol that allows editors and IDE’s like Emacs to talk to a language-specific service that understands the structure of the programming language and can provide navigation, code documentation, introspection, refactoring support and other actions and information. By externalising this functionality the same LSP server can be used by Emacs as is provided for VS Code, NeoVim or any other environment that supports LSP.
LSP is very lightweight, and the corresponding service programs of each programming language in LSP are different. To support a programming language, you only need to have the corresponding service programs.
Emacs’s built-in LSP manager is called eglot, which is used to start the service.
If use consult, When you write the code, try to run it: consult-imenu, consult-flymake, You will find surprises!
| Key | Cmmand | Comment |
|---|---|---|
| M-. | xref-find-definitions | Go to definition |
| M-, | xref-go-back | Back |
| C-M-, | xref-go-forward | Forward |
| M-? | xref-find-references | Find references |
(use-package eglot
:ensure nil
:if (>= emacs-major-version 29)
:hook
(eglot-managed-mode . (lambda () (eglot-inlay-hints-mode -1)));; No prompt is displayed
:hook
;; NOTE: Please add your programming language here
((c-mode c-ts-mode c++-mode c++-ts-mode rust-mode rust-ts-mode) . eglot-ensure)
:bind (:map eglot-mode-map
("C-c la" . eglot-code-actions) ;; Automatically write/repair code.
("C-c lr" . eglot-rename)
("C-c lf" . eglot-format) ;; Format current buffer
("C-c lc" . eglot-reconnect)
("C-c ld" . eldoc)) ;; view document
:custom
(eglot-autoshutdown t) ;; Automatically stop after closing all projects buffer
(eglot-report-progress nil);; Hide all eglot event buffers
:config
(setq eglot-stay-out-of '(company));; No other complementary backend options are changed
)Let’s say you’re writing a program in C. You’ll need to download the LSP program corresponding to C language: clangd ==> Releases · clangd/clangd · GitHub
clangd parses your code based on a configuration within the file: compile_commands.json
If you’re using Make or Cmake, you should be able find instructions on how to generate compile_commands.json for your project at compile time, with a quick internet search.
If your project is not using Make or Cmake, and you don’t already have a compile_commands.json, then you can use this method to generate it automatically:
- M-x freedom/compile-commands-json RET
- Select Project root dir
- Don’t worry, this command will not execute any compilation commands, it will only write the generated gcc compile command to
compile_commands.jsonfile
Note: If you are writing other programming languages, this may be different, for example, rust does not require compile_commands.json at all, rust only requires rust-analyzer.
(defun freedom/compile-commands-json ()
"Generate compile_commands.json for all .c/.C files in the selected directory.
Includes all directories containing .h/.H files as -I include paths."
(interactive)
(let* ((root (read-directory-name "Select project root: "))
(c-files (directory-files-recursively root "\\.\\(c\\|C\\)$"))
(h-dirs (let ((hs (directory-files-recursively root "\\.\\(h\\|H\\)$"))
(dirs '()))
(dolist (h hs)
(let ((dir (file-relative-name (file-name-directory h) root)))
(unless (member dir dirs)
(push dir dirs))))
dirs))
(json-file (expand-file-name "compile_commands.json" root))
(command-entries '()))
;; Construct the compile_commands.json project for each c file
(dolist (c-file c-files)
(let* ((rel-file (file-relative-name c-file root))
(obj-file (concat (file-name-sans-extension rel-file) ".o"))
(args (append
'("gcc" "-o")
(list obj-file "-g")
(mapcar (lambda (dir) (concat "-I" dir)) h-dirs)
(list rel-file)))
(entry `(("directory" . ,(expand-file-name root))
("arguments" . ,args)
("file" . ,rel-file))))
(push entry command-entries)))
;; Write JSON to compile_commands.json file
(with-temp-file json-file
(insert (json-encode command-entries)))
(message "compile_commands.json generated at: %s" json-file)))Org-mode is a writing tool (and much, much more), please go to the official website to learn more: Org mode for GNU Emacs
(use-package org
:ensure nil)README.org is an org-mode file that users can modify to directly generate the init.el configuration.
Call M-x org-babel-tangle RET in the README.org file will generate init.el.
